Verify ACP relay events before prompt routing - #7010
Conversation
Signed-off-by: Jordan Mecom <jm@squareup.com>
🔐 Codex Security Review
|
wpfleger96
left a comment
There was a problem hiding this comment.
🤖 Reviewed at head 0a05ea3 with two independent source reviews plus live adversarial E2E. The fix itself is solid — one IMPORTANT item is holding approval.
IMPORTANT — the new security regression tests run in no CI lane. The four tests live in crates/buzz-acp/src/relay.rs, but just test-unit's nextest list never runs buzz-acp, and the no-nextest fallback in scripts/run-tests.sh has the same omission. Server Cross-Compile is check/build only, and the Backend Integration nextest archive covers only buzz-db/buzz-relay/buzz-test-client. The green Unit Tests job therefore never executed these tests, which leaves this boundary fix unprotected against later regression. Mutation testing confirmed the tests do observe the production wiring (deleting the verification block fails all three adversarial tests), so wiring them into the gate is all that's needed: add cargo nextest run -p buzz-acp to the test-unit nextest branch and a matching cargo test -p buzz-acp -- --nocapture step to the fallback list. Heads-up: some pre-existing buzz-acp timing tests flaked when the package suite ran locally, so they may need attention when this lands in CI.
Everything else came back clean:
- Verification sits at the single choke point ahead of observer-control, membership, dedup/watermark, and harness-queue effects; the handshake-buffer replay path re-enters the same handler, so buffered pre-auth events are covered, and there is no other producer into either queue.
- Live E2E against a malicious relay: a forged owner
!shutdownwith recomputed ID was dropped with the expected log line, never reached ACP prompt routing, and a correctly signed owner message on the same connection one second later dispatched exactly one prompt. - The privilege-sensitive REST fetch paths (huddle instructions, canvas, engram core) already self-verify. One pre-existing, out-of-scope gap:
fetch_project_home_for_channelconsumes unverified events for prompt metadata — worth a small follow-up, not a blocker here.
Signed-off-by: Jordan Mecom <jm@squareup.com>
f6e5d60 to
0fec90a
Compare
|
@buzz-security-review 0fec90a |
What changed
Verify every Nostr EVENT received by buzz-acp immediately after deserialization. Events with an invalid NIP-01 ID or Schnorr signature are dropped before subscription routing, deduplication, replay-watermark updates, membership handling, or either harness queue.
Safety
Signature verification runs on the blocking pool so cryptographic work does not block the relay task. A verification failure drops only that event and keeps the connection available for subsequent valid traffic. The existing observer-control verification remains as defense in depth.
Regression tests cover valid delivery; changed content, ID, signature, pubkey, tags, and timestamp; a forged owner shutdown command with a recomputed ID; forged membership notifications; and forged observer-control events.
Testing
cargo test -p buzz-acp
cargo clippy -p buzz-acp --all-targets -- -D warnings
just ci