File: crates/replay/src/role.rs:275
Severity: robustness — availability
Obvious? yes — sibling-of-closed (#507 b075140)
PR #507 / b075140 capped peer-supplied HeadsSummary at MAX_AUTHORS_PER_SYNC = 256 in crates/storage/src/store.rs (sync_since + history) to defeat oversized cursors that would blow SQLite bind-parameter / expression-tree limits or just waste CPU compiling huge SQL.
Replay's handle_request(WorkerRequest::Sync { server_id, heads }) does the same per-author iteration on a peer-supplied HeadsSummary (heads.heads.iter().map(...).collect() then events_since) with no cap — malicious peer sends a multi-thousand-entry summary, forces O(N) BTreeMap inserts + walk through in-memory DAG. Identical DoS shape, trivially fixed by gating with the same constant.
Filed by /general-audit @ b901575 (2026-05-02). master: #513.
File:
crates/replay/src/role.rs:275Severity: robustness — availability
Obvious? yes — sibling-of-closed (#507 b075140)
PR #507 / b075140 capped peer-supplied
HeadsSummaryatMAX_AUTHORS_PER_SYNC = 256incrates/storage/src/store.rs(sync_since+history) to defeat oversized cursors that would blow SQLite bind-parameter / expression-tree limits or just waste CPU compiling huge SQL.Replay's
handle_request(WorkerRequest::Sync { server_id, heads })does the same per-author iteration on a peer-suppliedHeadsSummary(heads.heads.iter().map(...).collect()thenevents_since) with no cap — malicious peer sends a multi-thousand-entry summary, forcesO(N)BTreeMap inserts + walk through in-memory DAG. Identical DoS shape, trivially fixed by gating with the same constant.Filed by
/general-audit@b901575(2026-05-02). master: #513.