NIP-5D: nostr applets#2303
Open
dskvr wants to merge 2 commits intonostr-protocol:masterfrom
Open
Conversation
79ff1aa to
49d3bb7
Compare
This was referenced Apr 20, 2026
Expanded on iframe sandboxing requirements and added details about class-posture delegation for napplets.
This was referenced Apr 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
NIP-5D defines a
postMessageprotocol for sandboxed web applications ("napplets") running in iframes (or web-views) to communicate with a hosting application ("shell"). The NIP is deliberately a thin core: it specifies the envelope, sandbox rules, sender identification, and manifest-based capability negotiation. Actual protocol messages — relay access, storage, signing, theming, IFC, and so on — are defined by NUB (Napplet Unified Blueprint) extension specs, each of which owns a capability domain.NIP-5D depends on NIP-5A for napplet manifests and aggregate hash verification (see PR #2287).
What's in the spec
postMessagewith'*'target origin (required for opaque-origin sandboxed iframes). Sender identification viaMessageEvent.source(unforgeableWindowreference), notevent.origin.sandbox="allow-scripts"withoutallow-same-origin. Shells MUST NOT providewindow.nostr(NIP-07); signing and encryption are security-critical and mediated by the shell through NUB-defined APIs.{ "type": "<domain>.<action>", ...payload }. Thetypefield is adomain.actiondiscriminant where the domain corresponds to a NUB capability name (e.g., a NUB namedfooowns allfoo.*types). The NIP does not enumerate message types. Unknown types MUST be silently ignored to preserve forward compatibility.Windowreference to the(dTag, aggregateHash)tuple from the NIP-5A manifest. No handshake, no challenge-response, no negotiation. Messages from unmappedMessageEvent.sourcevalues MUST be silently dropped.["requires", "<nub-name>"]tags. Shells check these at load time and SHOULD reject or warn on mismatch.window.napplet.shell.supports('<capability>')returns a boolean. Capability strings are namespaced: bare/nub:for NUB capabilities (e.g.,'relay','nub:identity'),perm:for permissions (e.g.,'perm:popups'). Napplets MUST gracefully degrade when a capability is absent.MessageEvent.sourceidentity binding, aggregate hash verification against NIP-5A manifests, cleartext-only napplet output (shells MUST NOT sign or broadcast ciphertext supplied by a napplet), and silent-drop of unrecognized types to prevent capability probing.What's NOT in the spec
Specific protocol messages — relay proxy, signer proxy, storage, IFC, theming, feeds, chat, and so on — are defined externally as NUB (Napplet Unified Blueprint) proposals. The NUB ecosystem is organized into two tracks:
relay.*domain andwindow.napplet.relay, a storage NUB owningstorage.*andwindow.napplet.storage). One spec per domain name.This split keeps the NIP focused on the core primitive and lets the capability ecosystem iterate independently.
Implementations
There are already a few implementations, will be published soon.
Dependencies