Aller au contenu
login
arrow_backRetour aux issues
sipyourdrink-ltd/bernstein #3582

CAS sidecar read is exempt from the anchored walk on an assumption nothing enforces

ecoDébutant enhancement help wanted ai-welcome size/m core up-for-grabs

descriptionDescription

`CASStore._read_meta` reads the `.meta.json` sidecar without the anchored per-component walk that `CASStore.get` uses for blobs (#3577). That exemption is deliberate and currently sound: the sidecar is not content-addressed, so there is no digest to check it against, and an attacker able to plant a symlink in the store can equally write a hostile sidecar in place. Nothing in the verification path reads metadata. The exemption holds only while metadata stays descriptive. The condition that invalidates it — a caller making a trust decision from sidecar fields — is recorded in a docstring, and a docstring does not fail a build. What to do: - Decide whether a guard is warranted: either anchor the sidecar read through `open_anchored` as well (cheap, removes the reasoning burden entirely), or add a test/check that fails when a trust decision reads `CASEntry` fields. - If the second: enumerate the current readers of `_read_meta` / `CASEntry` and assert the set does not grow into verification paths. Not urgent. This exists so the assumption is re-examined by something other than memory. Brief for a coding agent Repo: `sipyourdrink-ltd/bernstein`. **Read the exemption before removing it.** `CASStore._read_meta` skips the anchored per-component walk that `CASStore.get` uses for blobs (#3577), and that exemption is currently sound: the sidecar is not content-addressed, so there is no digest to check it against, and an attacker who can plant a symlink in the store can equally write a hostile sidecar in place. The defect is not the exemption. It is that the condition invalidating it lives in a docstring, and a docstring does not fail a build. Starting point: `CASStore._read_meta` (`src/bernstein/core/persistence/cas_store.py:175`) and `CASStore.get` in the same module; `open_anchored` in `src/bernstein/core/persistence/anchored_read.py:79`. Failing-first assertion: whichever route you take, the test comes first. - If anchoring: a test that a sidecar reached through a symlinked component is refused, plus a positive control that an ordinary sidecar still reads. - If guarding: enumerate the current readers of `_read_meta` / `CASEntry` and assert the set does not grow into verification paths. That test fails the moment someone adds a trust decision, which is the whole point — so it has to name the current readers explicitly, not match a pattern. Verify commands: ``` uv run python scripts/run_tests.py tests/unit/storage/ tests/unit/security/ uv run mypy src/bernstein/core/ ``` Non-goals: making the sidecar content-addressed. Any change to blob reads. Decision left to you: anchor the read, or gate the readers. Anchoring is cheap and removes the reasoning burden entirely; the guard keeps the fast path and puts the assumption under CI instead of under memory. Both are defensible. If you anchor, say what it costs on a hot read path — that cost is the only argument for the other option.
codeOuvre sur GitHub