Files
buzz/docs/architecture/security-model.md
npub1pejagjwzjh7y36gq97hxf62ry75u3s6c6grr0rumx2p4c5qsms9s7jdtgl 23f75dac90 docs: write full documentation content (Phase 2)
Fill all 31 stub pages scaffolded in Phase 1 with content migrated and
verified from the root docs, crate READMEs, and source code:

- getting-started/ (3): installation, quickstart, local relay (TESTING.md)
- architecture/ (8): ARCHITECTURE.md §1–§8, one page per section
- guides/ (9): development, testing, agents, workflows, self-hosting,
  nostr-clients (operational half of NOSTR.md), adding-event-kinds,
  adding-api-endpoints, releasing
- reference/ (5): CLI reference verified against buzz --help and
  crates/buzz-cli/src (18 groups / 87 subcommands; README drift noted),
  configuration, known-limitations (ARCHITECTURE §9 + conformance
  LIMITS.md + doc-debt list), NIPs index (13, NIP-CW canonical),
  design-docs index
- vision/ (6): VISION.md + 5 VISION_*.md migrated with aspirational
  banners and rewritten links

Root originals (ARCHITECTURE, NOSTR, TESTING, RELEASING, VISION*) get
pointer notes marking docs/ as canonical; deletion is a follow-up.
All relative links in the new tree verified to resolve.

Known limitations are documented honestly, never papered over:
rate limiting unenforced, WF-07/WF-08 workflow stubs, buzz-cli README
drift, one-line GOVERNANCE.md.

Note: pre-commit sadscan findings reviewed as false positives (dev-default
postgres URI and NIP-OA test vectors, both already on origin/main).

Co-authored-by: npub1pejagjwzjh7y36gq97hxf62ry75u3s6c6grr0rumx2p4c5qsms9s7jdtgl <0e65d449c295fc48e9002fae64e94327a9c8c358d206378f9b32835c5010dc0b@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: npub1pejagjwzjh7y36gq97hxf62ry75u3s6c6grr0rumx2p4c5qsms9s7jdtgl <0e65d449c295fc48e9002fae64e94327a9c8c358d206378f9b32835c5010dc0b@sprout-oss.stage.blox.sqprod.co>
2026-07-07 12:14:33 -07:00

3.1 KiB

Security Model

Every security-sensitive operation in Buzz uses an explicit, verified pattern — no implicit trust. This page covers authentication, input validation, SSRF protection, audit integrity, access control, and webhook security. To report a vulnerability, see SECURITY.md at the repository root. Multi-tenant isolation is formally specified in docs/multi-tenant-relay.md and the docs/spec/ TLA+/Tamarin models.

Every security-sensitive operation uses an explicit, verified pattern. No implicit trust.

Authentication

Concern Mechanism
NIP-42 timestamp ±60 second tolerance — prevents replay attacks
AUTH events Never stored in Postgres, never logged in audit chain
NIP-98 HTTP Auth Schnorr-signed kind:27235 events — URL and method verification

Input Validation

Concern Mechanism
Schnorr signatures verify_event() in buzz-core — every event verified before storage
Event ID SHA-256 of canonical serialization verified independently of signature
Frame size MAX_FRAME_BYTES = 65,536 — oversized frames rejected, connection closed
Search event IDs 64-char hex validation before URL construction — prevents path injection
Workflow step IDs Alphanumeric + underscore only — prevents evalexpr variable injection
Partition names Allowlist of table names + strict suffix/date validators — prevents DDL injection

SSRF Protection

is_private_ip() in buzz-core covers:

  • IPv4: unspecified (0.0.0.0/8), loopback (127.0.0.0/8), private (10/8, 172.16/12, 192.168/16), link-local (169.254/16), CGNAT (100.64/10), benchmarking (198.18/15), broadcast (255.255.255.255)
  • IPv6: loopback (::1), ULA (fc00::/7), link-local (fe80::/10), multicast (ff00::/8), documentation (2001:db8::/32)
  • IPv4-mapped IPv6 (::ffff:0:0/96) — recursively checks the embedded IPv4 address

Applied in: buzz-workflow (CallWebhook action), buzz-core (shared utility).

Audit Integrity

  • Hash chain: each entry's SHA-256 covers all fields including prev_hash — tampering any entry breaks all subsequent hashes
  • Canonical JSON: BTreeMap for deterministic key ordering — hash is reproducible
  • Single-writer lock: pg_advisory_lock — prevents concurrent writes from breaking the chain
  • Panic-safe: catch_unwind ensures lock release even on panic

Access Control

  • Channel membership is the only gate — enforced by the relay at every operation
  • REQ handler checks access before subscription registration — no race window for private channel leaks
  • TOCTOU-safe membership operations: all check-then-modify sequences run inside Postgres transactions
  • Approval tokens: UUID (CSPRNG), stored as SHA-256 hash, single-use enforced with AND status = 'pending' in UPDATE

Webhook Security

  • Workflow webhooks: constant-time XOR comparison of stored UUID secret (not HMAC — compares the secret directly, not a body MAC)
  • Outbound webhooks (CallWebhook): SSRF protection + redirects disabled + 1 MiB response cap