S1 — NIP-40 expiration on kind-21000 RPC events #15
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #13. Closes gap G4 (no replay window on RPC events).
Problem
A relay can stash and replay a legitimate kind-21000 RPC. NIP-44 v2 encryption protects content + integrity but does not protect against replay. Today the LNbits nostr-transport handler accepts events up to ~10 min old; that's a long replay window.
Fix
Every kind-21000 event carries
["expiration", <unix_ts_5_minutes_from_now>](NIP-40). Handler refuses events past expiration.Changes
ATM side (
aiolabs/lamassu-next)["expiration", now + 300]tag.Handler side (
aiolabs/lnbitsnostr-transport)expiration < nowin the dispatcher.This repo (
aiolabs/satmachineadmin)Paymentobjects, not raw kind-21000 events. But: if we ever publish kind-21000 outbound (we don't today, but management commands per #42 will), they get the same tag.Acceptance
journalctl -u bitspire.Reference
NIP-40 spec:
~/dev/nostr-protocol/nips/40.md.Design doc:
docs/security-pathway-v1.md§5.1, §6.S1.Closing as done — both sides shipped.
LNbits handler side (
aiolabs/lnbitsnostr-transport branch,e4b5bcd7):max_agewindow of 300s (configurable vianostr_transport_max_age_seconds) oncreated_at— defends against replay even when the sender omits the expiration tag.nostr_transport_future_skew_seconds, default 60s) bounds "valid forever" forgery while tolerating honest client-clock drift.ATM emission side (
aiolabs/lamassu-nextdevbranch,b52a116):packages/lnbits/src/client.ts:sendRpc()appends['expiration', String(now + 300)]to every kind-21000 envelope. Defence-in-depth at the relay layer — compliant relays drop expired events before they reach LNbits.Acceptance criteria status:
Gap G4 closed.
Follow-up: NTP-drift warning on ATM startup. Will file on
aiolabs/lamassu-nextif it doesn't already exist there.