Repository navigation
Description
Destination
Audit findings #1–#4 and #6 from the 2026-07-09 security audit fixed, tested, and merged to main, with scripts/run-demo.sh green end-to-end at close; the MCP URL policy decided (ADR'd if needed); socket DoS budgets (finding #5) either fixed in-map or explicitly deferred to a tracked issue.
Notes
- Execution is in-map (override of wayfinder's plan-only default): fix tickets end in merged PRs, not decisions.
- Work all fixes in
.worktrees/<slug>/per repo worktree discipline; one conceptual change per PR. - AFK tickets end in a PR; Toni reviews and merges — nothing lands unreviewed. HITL (grilling) tickets resolve only with Toni live.
- Fixes ship in the open with plain commit messages, no advisory. Revisit trigger: if a design partner or any external deployment materializes before map close, revisit disclosure.
- Verification bar: every fix PR carries regression tests for its specific hole; failure-injection tests where a fix touches 2PC commit plumbing; the
get_rawfix re-checks snapshot-model §9 perf targets; the map closes only with the Postgres CI suites and the full demo green onmain. - ADR-0014 was accepted as written (Status flipped 2026-07-09, charting session). If implementation finds it underspecifies something load-bearing (key provisioning, TTL, CLI UX), stop and surface a decision — don't invent policy.
- Charting decisions (2026-07-09): destination = fixes landed, not plan-only; tiering = findings Bump Rust toolchain to 1.95.0 #1–Chunk D (part 1): trigger-based streamer + delta-sized snapshots #4 and chore: ignore agent-harness runtime state, keep main clean #6 must-fix, Chunk D (part 2): pg_advisory_lock serialises snapshots across processes #5 defer-or-fix; interim hard-reject ships first and is superseded by the full gate; finding Chunk D (part 1): trigger-based streamer + delta-sized snapshots #4 split into caps (straight fix) + URL policy (decision, then fix); Postgres CI job lands early as the harness.
- Per-finding evidence (file:line) lives in each ticket body.
Decisions so far
- Interim hard-reject of accept_data_loss=true rollbacks — shipped fail-closed (PR Reject accept_data_loss rollbacks until the ADR-0014 approval gate ships #114, merged): every accept_data_loss=true rollback rejected before side effects with typed ApprovalError, wire code approval_key_not_configured shared with the full gate; demo path confirmed unaffected.
- Branch-name validation in Refs (path traversal fix) — shipped (PR Validate branch names before building ref paths under refs/heads #115, merged): central validate_branch_name at the branch_path chokepoint, typed InvalidBranchName / wire code invalid_branch_name; nested names still supported, rollback targets covered via resolve with no daemon changes.
- Postgres+pgvector CI job running the ignored integration suites — shipped (PR Run the ignored Postgres integration suites in CI against real pgvector #116, job green on its own CI run in ~2m): 21 Postgres tests now run per-PR; memory suite needs --test-threads=1 per its documented shared-change_log contract.
- MCP response caps: streaming byte limit, JSON depth, manifest size — shipped (PR Cap MCP response size, JSON depth, and manifest size in the fingerprinter #117, merged): McpLimits (1 MiB response streamed, depth 32, 1 MiB manifest) enforced under commit_lock; URL-policy half untouched per the split; McpLimits is the config seam if the URL decision wants knobs.
- Verify content hashes on every get_raw() read — merged (PR Verify content hashes on every get_raw() read #120)
- Implement the decided MCP URL policy — merged (PR Enforce the MCP URL policy: HTTPS-except-loopback + no redirects (ADR-0016) #122): ADR-0016 written; validate_mcp_url (HTTPS-except-loopback) enforced at startup, redirects disabled on the daemon client with Location surfaced, no allowlist by construction. Demo unaffected.
- Read-idle timeout on the agenticd connection loop — merged (PR Add a read-idle timeout to the agenticd connection loop #123): per-frame READ_IDLE_TIMEOUT (30s), log-and-close on elapse, resets per frame; the DoS carve-out (rest deferred to Socket availability hardening: connection caps, per-UID budgets, queue-depth metrics #118). Injectable timeout for fast tests.
- Map-close verification: full demo green on main — closed on the security destination: 6 fixes verified present in main HEAD, CI green; demo-green reinterpreted per CLAUDE.md 'aspirational' and deferred to Demo (run-demo.sh) does not run green from a clean state — 5 gaps + baseline-ask hang #124 (pre-existing demo/SDK hang, proven independent of the security work).
- Implement ADR-0014: destructive-rollback approval gate — merged (PR Implement ADR-0014 destructive-rollback approval gate #121): full HMAC gate re-established (the interim gate was silently dropped by Validate branch names before building ref paths under refs/heads #115's merge-conflict resolution — main was unprotected). Constant-time verify, zeroizing key, --approval-key-file, CLI token issuance, audit events, all rejection variants tested.: check_integrity chokepoint; get_raw verifies Hash::of(bytes), GCS fetch_checked evicts poisoned cache + never caches a corrupt download; added BLAKE3 cost ~0.5ms/MiB, §9 unaffected.
- Decide the MCP URL policy (HTTPS, allowlist, ADR?) — decided: HTTPS required except loopback (no escape hatch); redirects disabled on the daemon client (the real SSRF vector — reqwest was following 10 by default); no separate allowlist, by construction; ADR-0016 to be drafted in the implementation ticket.
- Decide socket DoS budgets: fix in-map or defer — deferred (weakest threat model: single-tenant co-located sidecar, own worker is the only peer), carving out an in-map read-idle-timeout ticket; rest → backlog issue Socket availability hardening: connection caps, per-UID budgets, queue-depth metrics #118 with a revisit trigger.
MAP COMPLETE (2026-07-10): closed on the security destination (Toni's decision). All six audit findings fixed, tested, merged, and verified present in
mainHEAD. The literal "run-demo.sh green" criterion was reinterpreted per CLAUDE.md's "aspirational" framing; the demo's baseline-ask hang + portability gaps are proven independent of the security work and carried forward as issue #124.
Not yet specified
Out of scope
-
Demo runnability (run-demo.sh hangs at baseline ask + release-strip / SUN_LEN / python3 / agent-deps portability gaps) — beyond the security destination and proven independent of it; tracked in issue Demo (run-demo.sh) does not run green from a clean state — 5 gaps + baseline-ask hang #124. See Map-close verification.
-
Socket availability hardening beyond a read-idle timeout (connection/per-UID caps, rate budgets, queue-depth metrics, write-idle deadline) — deferred to backlog issue Socket availability hardening: connection caps, per-UID budgets, queue-depth metrics #118 by the Decide socket DoS budgets: fix in-map or defer #109 decision; the v1.0 single-tenant sidecar threat model doesn't warrant it. Revisit on any wider deployment shape or the first design partner.
-
KMS-backed approval signing — v1.1 per ADR-0014 Decision 6.
-
Anything past the broken-prompt demo path (memory backends, framework integrations, web UI) per the CLAUDE.md scope boundary.
Activity
Reject accept_data_loss rollbacks until the ADR-0014 approval gate sh…
Cap MCP response size, JSON depth, and manifest size in the fingerpri…
tonibergholm commentedon Jul 10, 2026
Map complete. The 2026-07-09 security-audit remediation is done: all six findings fixed, tested, merged, and verified present in
mainHEAD (two criticals — branch-path traversal, self-authorized destructive rollback; two highs — get_raw integrity, MCP response caps; two mediums — MCP URL policy, socket read-idle timeout), plus the Postgres CI harness. Two ADRs landed (0014 Accepted, 0016 written). A live regression (the #115 merge silently dropping the interim gate) was caught and fixed. Demo-runnability is carried forward as #124, outside this map's destination per Toni's close decision.