Files
clawhdf5/research/02_security.md
Omar Sobh b08df7b628 clawmates: phase work
Mission: 01a00c41-bac0-7eb3-a8c8-8b7044f3086d
Phase: 01a00c41-bac2-71e3-a58b-c473421200ee

Committed by the ClawMates delivery pipeline from the agents' working tree. Authored by agents, not by the named committer.
2026-08-16 20:44:28 +00:00

43 lines
2.4 KiB
Markdown

# Research: Security — clawhdf5
Scope: opportunities not already covered by the shipped hardening (WAL CRC32
trailer / `WAL_VERSION` 2, `MAX_WAL_FIELD_LEN` field caps, Android JNI length
validation, `chunked_read.rs`/`data_read.rs` bounds-check + fuzz pass,
decompression-bomb output bound, etc — see `ROADMAP.md`).
## Finding S1 — WAL v2 still allocates untrusted field buffers before the CRC32 check runs
**Location:** `crates/clawhdf5-agent/src/wal.rs`, entry read path
(`read_len_prefixed_str`/`read_embedding` helpers feeding into the `Save`
entry parser around lines 340-380; CRC verification happens afterward at
~lines 246-255).
**Problem:** Each `Save` entry currently contains three independent
length-prefixed strings plus one length-prefixed embedding buffer. Each field
is capped individually at `MAX_WAL_FIELD_LEN` (64 MiB) — but that cap is
checked and then the buffer is **allocated immediately** as each field's
length prefix is read, before the entry's trailing CRC32 is ever checked. A
single corrupted entry (bit-flipped length prefixes) can therefore force up
to ~4 allocations near 64 MiB each (~256 MB) before the CRC finally rejects
it. This is exactly what `ROADMAP.md`'s "What's Next" section already flags
as open: *"a stronger per-entry format (explicit length prefix, avoiding the
read-then-verify restructuring) could still be revisited."*
**Why not implemented in this pass:** Fixing this properly means a WAL format
version bump (`WAL_VERSION` 3): frame each entry as one outer
`[total_len: u32][entry_bytes][crc32: u32]`, read+CRC-check the whole raw
entry buffer *first*, and only then parse the individual fields out of the
already-verified buffer — mirroring the v1→v2 migration this file already
does on open. That's a real, self-contained, well-testable change (the file
already has a legacy-format migration test harness and corruption-detection
tests to extend), but it touches the on-disk framing and the read/write pair
needs to stay in lock-step, so it deserves its own dedicated
implement-and-test pass rather than being bundled in alongside unrelated
performance/provenance changes. Tracked as **INT-04** below for follow-up.
## Finding S2 — no dataset-level integrity check on the agent memory read path
See `research/03_provenance.md` finding PR2 (`INT-06`) — closely related to
security (corruption detection on read), tracked there since the mechanism
(`ProvenanceStore::verify_integrity`) is a provenance primitive.