Skip to content

general-audit: main @ 0de7631 (2026-04-29) #492

@intendednull

Description

@intendednull

Main @ 0de7631b12b630b402faaac1df2079f63246566d (merge of #489). Prior audit @ 958e1ec (#474). Run via /general-audit.

Method

Per lessons #426 / #438 / #474 / #477: orchestrator-direct default for diffs under ~100 files / ~2000 LOC; pre-fetch existing-issue lists; orchestrator runs cargo-audit; sibling-of-closed pass on closed-since-last-audit.

  • 0 agents launched. 66-file / +12733 −4961 LOC diff. Over the file-count threshold but under the finding-density threshold; orchestrator-direct still scaled because new code clusters in 3 areas (test-hooks foundation, voice/governance test landings, ProfileState/typing caps).
  • Pre-fetched existing-issue lists: /tmp/audit-issues.txt (17 entries), /tmp/security-issues.txt (26 entries), tech-debt list inline (17 entries). Total 60 unique titles for dedup.
  • Orchestrator ran cargo-audit directly. Clean vs CI ignore list (8 RUSTSEC IDs); 5 of 8 still match advisory DB, 3 ignore-list IDs no longer match anything (advisories may have been dropped upstream — non-finding).
  • Sibling-of-closed pass on PRs closed since 958e1ec. F1 + F2 are exactly siblings of ci:-titled commits whose actual scope was narrower than the bug class — 950e376 only edited just check-all, bd1f725 only added an eslint config file. CI workflows were never edited.
  • Direct main-context sweeps for: unsafe, dbg!/eprintln!/todo!/unimplemented!, Arc<Mutex>/Arc<RwLock> w/o lock-ok, panic!/unwrap in lib prod, js_sys::eval/innerHTML, TODO/FIXME/HACK, anyhow:: in pure libs, vector caps in wire types, let _ = h.<method>().await swallow (per general-audit lessons: 2026-04-28 #477 lesson), CSP, docker pin/USER hardening, SQL prep statements, voice cap enforcement, identity malformed-bytes tests.
  • Diff @ 958e1ec..0de7631: 58 commits / ~30 PRs / 66 files / +12733 −4961.

Major themes since last audit

Concerns audited

Concern Method Result
security: input-validation/DoS direct strong (caps verified: SEC-V-03 voice, SEC-V-05 typing/profile, MAX_EVENT_DEPS, MAX_DESER_SIZE)
security: auth/permissions direct strong (state-machine permissions tests comprehensive, apply_event enforces)
security: web/WASM direct strong; CSP added (one weakening from 'unsafe-eval' documented), test-hooks privacy guard exists but F1 found
security: deps/supply-chain orchestrator (cargo audit) clean vs ignore list (5 RUSTSEC IDs match)
tech debt direct stable; existing trackers cover (#332 #320#330 #195 #485 #481), F2 found
architecture (spec drift) direct lock-ok comments compliant w/ docs/specs/2026-04-26-state-management-model-design.md (12 sites, all annotated)
general direct F1 + F2 are CI-wiring gaps
test coverage direct new tests landed: voice (6) + governance (5) + actions + identity malformed; state tests split + 4802 LOC; actor shutdown/broker-fanout tests added

Strong areas (re-verified, no findings)

  • crates/state/src purity: zero tokio / iroh:: / std::fs / SystemTime (rg "tokio::|std::fs|SystemTime|iroh::" crates/state/src clean)
  • pure-lib anyhow: zero hits in crates/{state,transport,identity,messaging,crypto,common}/src
  • wire deserialize defense-in-depth: MAX_DESER_SIZE = 256 KB + per-variant WireMessage::max_size
  • event-DAG insert: MAX_EVENT_DEPS = 64, MAX_ENCRYPTED_KEY_BYTES = 128
  • MAX_PROFILE_NAMES = 10_000, MAX_TYPING_PEERS = 10_000, LRU evict, 5s TTL sweep
  • MAX_VOICE_CHANNELS = 256, voice-join gated on known channel id
  • voice + governance + actions + ephemeral + multi_peer_sync + queue + trust + profile_view test files (8 dedicated test modules)
  • state tests split: dag.rs (708) + materialize.rs (1916) + permissions.rs (1087) + stress.rs (387) + sync.rs (247) + voting.rs (457) = 4802 LOC
  • lock-ok comments on every legitimate lib-crate Arc/Arc (12 sites: 4 client, 1 actor test, 1 web state_bridge cached, plus search/* doc-comment-only references)
  • unsafe sites all annotated (crates/actor/src/addr.rs:91 Sync for Addr, crates/web/src/state_bridge.rs:98 Send for DerivedStateActor)
  • no unimplemented!() / todo!() / dbg!() / eprintln!() / FIXME / HACK in lib production
  • web js_sys::eval sites: 1 user-input-interpolated ([WS-1] Web: js_sys::eval(format!()) for pinned-message scroll uses band-aid sanitization #425 [WS-1] tracked), rest static-string — no new XSS surface
  • docker images: digest-pinned rust:1.95-slim-bookworm, nginxinc/nginx-unprivileged:1.27-alpine, all containers run USER willow/USER nginx, trunk pinned 0.21.14
  • let _ = h.<method>().await zero hits across web (F2 from general-audit: main @ 958e1ec (2026-04-28) #474 properly fixed)
  • SQL queries in crates/storage/src/store.rs: parameterized (?N), values passed via Box<dyn ToSql> — no concatenation injection surface
  • test-hooks gated behind default = [], WillowTestHooks symbol absent from prod under spec — but enforcement gap, see F1

Findings (2 child issues)

# Sev Title
F1 medium scripts/check-no-test-hooks-in-prod.sh symbol-leak guard not wired into CI / deploy workflows — only just check-all
F2 low eslint.config.js bans waitForTimeout but no CI step or npm script runs eslint

Both findings = sibling-of-closed pattern. The ci:-prefixed commits (950e376, bd1f725) only edited local just recipe / config file but never touched .github/workflows/.

Findings deemed not actionable (verified during sweep)

Existing-issue overlap (not re-filed)

Method change vs #474

Lessons follow-up issue describes outcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions