Enforce NIP-OA authorization time bounds - #7004
Conversation
Signed-off-by: Jordan Mecom <jm@squareup.com>
🔐 Codex Security Review
|
|
@buzz-security-review 51ad528 |
Signed-off-by: Jordan Mecom <jm@squareup.com>
wpfleger96
left a comment
There was a problem hiding this comment.
🤖 Reviewed at head 2e6edd6 alongside an independent second source review and live E2E verification — all three came back clean.
Both source reviews traced the verified timestamp from NIP-42, NIP-98, Git, and Blossom auth through every enforce_relay_membership() / extract_nip_oa_owner() consumer, and confirmed strict bound semantics, canonical hex enforcement, duplicate x-auth-tag rejection, and the X-Pubkey fail-closed path. Live testing ran this head as a closed relay (BUZZ_REQUIRE_RELAY_MEMBERSHIP=true, BUZZ_ALLOW_NIP_OA_AUTH=true) with 15/15 targeted scenarios passing over real NIP-42 WebSocket and NIP-98 HTTP, including equality-boundary denials, expired credentials, dual auth tags, duplicate headers, and the direct-member regression path.
No findings.
NIP-OA relay admission now evaluates signed
created_at<andcreated_at>conditions against the already verified authentication event timestamp. An owner-signed credential such ascreated_at<1no longer upgrades its holder to relay membership.The verified timestamp now flows from NIP-42, NIP-98, and Blossom authentication through the shared membership gate used by WebSocket, HTTP, Git, media, huddles, GIF, and workflow requests. Owner-attested access fails closed when no signed authentication timestamp is available. Direct relay members keep their existing admission behavior, and
kind=remains connection-level metadata as specified by NIP-AA.Tests cover strict time-bound evaluation, missing timestamp rejection, and HTTP authentication timestamp propagation.
Testing:
cargo test -p buzz-sdk nip_oa::tests -- --nocapturecargo test -p buzz-relay api::relay_members::tests -- --nocapturecargo test -p buzz-relay api::bridge::tests -- --nocapturejust ci