Summary
repo_store::acquire's cache-miss path (crates/gitlawb-node/src/git/repo_store.rs:180-193) runs tigris.exists + tigris.download per concurrent caller with no in-flight dedup, and download buffers the entire archive in memory (crates/gitlawb-node/src/git/tigris.rs:127-134, resp.body.collect().into_bytes(); the upload side likewise builds the whole tar.zst in RAM, :86-93). The publish_lock serializes only the final swap (#343). The anonymous read handlers that reach acquire (tree/blob/changelog REST routes) have no timeout clamp or admission, unlike git_info_refs/upload-pack//ipfs.
Impact
N concurrent cold hits on a Tigris-backed node produce N parallel full-archive downloads and N temp-dir unpacks: memory and bandwidth multiply by archive size (hundreds of MB) with no per-IP brake. Extends the #343 admission family with a cold-path amplification member.
Remediation
- Single-flight the cold acquire per repo (in-flight map or per-repo permit).
- Stream the download to disk instead of buffering, and cap archive size.
Proposed labels: kind:security, crate:node, subsystem:storage.
Summary
repo_store::acquire's cache-miss path (crates/gitlawb-node/src/git/repo_store.rs:180-193) runstigris.exists+tigris.downloadper concurrent caller with no in-flight dedup, anddownloadbuffers the entire archive in memory (crates/gitlawb-node/src/git/tigris.rs:127-134,resp.body.collect().into_bytes(); the upload side likewise builds the whole tar.zst in RAM,:86-93). Thepublish_lockserializes only the final swap (#343). The anonymous read handlers that reachacquire(tree/blob/changelog REST routes) have no timeout clamp or admission, unlike git_info_refs/upload-pack//ipfs.Impact
N concurrent cold hits on a Tigris-backed node produce N parallel full-archive downloads and N temp-dir unpacks: memory and bandwidth multiply by archive size (hundreds of MB) with no per-IP brake. Extends the #343 admission family with a cold-path amplification member.
Remediation
Proposed labels: kind:security, crate:node, subsystem:storage.