Files
buzz/SECURITY.md
Cea Stapleton Cordasco 633260e404 docs(nip-fi): close outstanding review findings
Replace the flat future configuration draft with a multi-domain revision, separate denial observation from the non-reclaimable authorization-audit budget, and clarify current runtime behavior.

Document lifecycle and denial-oracle rationale and carry the complete transport, lease, invalidation, and conformance obligations into the implementation handoff.

Signed-off-by: Cea Stapleton Cordasco <261786559+cea@users.noreply.github.com>
2026-08-12 17:31:07 -05:00

6.2 KiB

Security Policy

Reporting a Vulnerability

Please do not report security vulnerabilities through public GitHub issues.

If you discover a security vulnerability in Buzz, please report it by emailing security@buzz-relay.org. Include as much detail as possible:

  • A description of the vulnerability and its potential impact
  • Steps to reproduce or a proof-of-concept (if available)
  • The affected version(s) or commit range
  • Any suggested mitigations you've identified

You will receive an acknowledgment within 48 hours. We aim to provide a full response — including a timeline for a fix — within 7 days of initial contact. We'll keep you informed as we work toward a resolution.

We ask that you:

  • Give us reasonable time to address the issue before any public disclosure
  • Avoid accessing or modifying data that does not belong to you
  • Not perform denial-of-service attacks or disrupt production systems

We will credit reporters in release notes unless you prefer to remain anonymous.


Supported Versions

Version Supported
main (latest) ✅ Active
Previous releases ⚠️ Best-effort; upgrade recommended

Buzz is pre-1.0. We do not maintain long-term support branches at this stage. All security fixes land on main first.


Security Design Principles

Authentication — NIP-42

Every connection to the relay must authenticate via NIP-42 challenge/response before writing events. The relay sends a random challenge; the client signs a kind:22242 event containing the challenge and the relay URL, proving possession of the private key.

REST endpoints authenticate via NIP-98 HTTP Auth — the client signs a kind:27235 event containing the request URL and method. The relay verifies the Schnorr signature and extracts the pubkey.

Authorization and admission

In the current merged runtime, channel membership is Buzz's only application-level access-control mechanism. If a principal (human or agent) is a member of a channel, application policy may allow them to read and write it. If they are not a member, the relay rejects their requests even if they are authenticated.

Private channels are invisible to non-members: they do not appear in channel listings, and subscription filters for private channel events return nothing unless the subscriber is a member.

NIP-FI defines a future optional additional admission authority that combines provider-neutral issuer assertions with fresh Nostr key proof, current durable binding and lifecycle state, and final application admission. When enabled for a domain, one current NIP-FI authority covers every protected ingress atomically, and both NIP-FI and application authorization must allow each operation. NIP-FI does not replace NIP-42, NIP-98, Nostr signatures, channel membership, or resource policy.

That NIP-FI behavior is not shipped in the current merged runtime. This documentation revision does not include or activate a NIP-FI runtime adapter. A later exact-head implementation and deployment must pass the behavioral evidence matrix before publishing discovery or enforcing the contract. Source scans, prose, and configuration presence do not establish conformance. See the threat model, stock deployment, and runtime operations.

Append-Only Audit Log

All events are written to a tamper-evident audit log (buzz-audit). Each log entry is chained to the previous one via a SHA-256 hash chain. Because the chain is keyless, it is tamper-evident but not tamper-resistant: it detects accidental corruption or single-row edits, but an attacker with database write access can recompute the entire chain after editing. The audit log is designed for SOX-grade compliance and eDiscovery.

Desktop Secret Storage — OS Keyring

The Buzz desktop app stores nsec private keys in the operating system keyring rather than in plaintext files: macOS Keychain, Windows Credential Manager, or the Linux Secret Service (gnome-keyring / kwallet via D-Bus). This covers both the human identity key and every managed-agent key.

On first launch after upgrading, existing plaintext keys are migrated into the keyring: the key is imported, read back to verify the round-trip, and only then is the plaintext deleted. Migration runs only when the keyring is reachable — if the backend is unavailable that session, the app keeps reading from the plaintext file and does not migrate, so a transient outage cannot resurrect a rotated key from a leftover file.

When no keyring backend is available (headless Linux with no Secret Service, for example), keys fall back to a 0o600 owner-only file. The BUZZ_PRIVATE_KEY environment variable, when set, always takes precedence over both stores — this is how harnessed agents and CI receive their identity.

Input Validation

  • All UUIDs (channel IDs, workflow IDs) are validated at API boundaries before use in database queries.
  • Workflow call_webhook actions are SSRF-protected: the target URL is resolved and checked against a blocklist of private/loopback address ranges before the request is made.
  • Workflow response bodies are size-limited to prevent memory exhaustion.
  • evalexpr condition evaluation is sandboxed and timeout-bounded.
  • Query parameters passed to external URLs are percent-encoded to prevent injection.

Transport Security

All production deployments should terminate TLS at the relay or a reverse proxy in front of it. The relay itself does not enforce TLS — this is intentional to allow flexible deployment behind load balancers and ingress controllers.

Dependency Management

We use cargo audit in CI to scan for known vulnerabilities in dependencies. #![deny(unsafe_code)] is enforced across all crates — no unsafe Rust.


Disclosure Policy

We follow coordinated disclosure. Once a fix is ready and released, we will publish a security advisory on GitHub describing the vulnerability, its impact, and the fix. Reporters will be credited unless they request anonymity.