fix: begrens het lezen van beeld-sidecars #542

Merged
brenno merged 1 commit from feat/beveiligingsharding into main 2026-07-22 11:38:56 +00:00
Owner

Summary

The first of the nine items in #516: the unbounded sidecar reads. Partial — #516 stays open.

What was wrong

All three read paths in ImageSidecarStore read the file with no size check. A sidecar travels with a deck, so it can arrive from a package, a repository, or somebody else's folder — jsonDecode then puts a second copy on top of the first.

The write path was the sharper one. Without a cap, write() carried on with an empty map, wrote that over the file, and every other caption in that folder was gone. That is precisely the failure the existing catch block next to it describes and defends against — reached by a different route.

The cap

1 MiB. The file is a flat map of filename to caption, so that is room for thousands of images. The excess is logged rather than swallowed: silently skipping makes the user believe their captions are gone when they are still on disk.

Verification

Three tests, including that a too-large sidecar is left byte-identical after a write attempt. Mutation-checked: removing the cap makes two of the three fail.

make check green.

Still open in #516

The other eight items, of which two deserve a note now:

  • audienceBoundary generic — I measured this before attempting it. There are 208 raw Deck/List<Slide> parameters across 67 files outside privacy/, so the obvious inversion ("baseline every Deck-taking function") produces noise rather than signal. A workable generic rule has to key on output — a function that takes a raw deck and reaches an output primitive — which is a real design, not a quick fix. Worth doing, not worth guessing at.
  • PBKDF2-SHA1 at 1000 iterations is already recorded as a deliberate deviation in assurance/ASVS-5.0.0-afwijkingen.md with its reasoning. It should be resolved there if it is resolved, not re-decided in a hardening pass.
## Summary The first of the nine items in #516: the unbounded sidecar reads. Partial — #516 stays open. ## What was wrong All three read paths in `ImageSidecarStore` read the file with no size check. A sidecar travels with a deck, so it can arrive from a package, a repository, or somebody else's folder — `jsonDecode` then puts a second copy on top of the first. **The write path was the sharper one.** Without a cap, `write()` carried on with an empty map, wrote that over the file, and every other caption in that folder was gone. That is precisely the failure the existing `catch` block next to it describes and defends against — reached by a different route. ## The cap 1 MiB. The file is a flat map of filename to caption, so that is room for thousands of images. The excess is logged rather than swallowed: silently skipping makes the user believe their captions are gone when they are still on disk. ## Verification Three tests, including that a too-large sidecar is left **byte-identical** after a write attempt. **Mutation-checked:** removing the cap makes two of the three fail. `make check` green. ## Still open in #516 The other eight items, of which two deserve a note now: - **`audienceBoundary` generic** — I measured this before attempting it. There are 208 raw `Deck`/`List<Slide>` parameters across 67 files outside `privacy/`, so the obvious inversion ("baseline every Deck-taking function") produces noise rather than signal. A workable generic rule has to key on *output* — a function that takes a raw deck **and** reaches an output primitive — which is a real design, not a quick fix. Worth doing, not worth guessing at. - **PBKDF2-SHA1 at 1000 iterations** is already recorded as a deliberate deviation in `assurance/ASVS-5.0.0-afwijkingen.md` with its reasoning. It should be resolved *there* if it is resolved, not re-decided in a hardening pass.
fix(beveiliging): begrens het lezen van beeld-sidecars
Some checks failed
CI / Gate (Linux) · Format · Analyze · Coverage (push) Has been cancelled
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Web hardening (push) Has been cancelled
CI / Docs links (push) Has been cancelled
CI / Supply-chain (Trivy · advisory) (push) Has been cancelled
CI / Gate (Linux) · Format · Analyze · Coverage (pull_request) Has been cancelled
CI / Test (macos-latest) (pull_request) Has been cancelled
CI / Test (windows-latest) (pull_request) Has been cancelled
CI / Web hardening (pull_request) Has been cancelled
CI / Docs links (pull_request) Has been cancelled
CI / Supply-chain (Trivy · advisory) (pull_request) Has been cancelled
5c9fea019b
Een sidecar reist mee met een deck — uit een pakket, een repo, of een map
van iemand anders. Alle drie de leespaden in ImageSidecarStore lazen hem
onbegrensd in, en jsonDecode legt er nog een kopie bovenop.

De schrijfkant was de scherpste. Zonder grens ging write() door met een
lege map, schreef die over het bestand heen, en waren alle andere
bijschriften in die map weg — precies de fout die het catch-blok ernaast
beschrijft, alleen met een andere aanleiding.

Eén MiB is ruim voor duizenden afbeeldingen; het gaat om een platte map
van bestandsnaam naar bijschrift. Het overschot wordt gemeld, want stil
overslaan laat de gebruiker denken dat zijn bijschriften weg zijn terwijl
ze er nog staan.

Getoetst met een mutatie: de grens weghalen laat twee van de drie tests
vallen.

Onderdeel van #516.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit cde5bc0969 into main 2026-07-22 11:38:56 +00:00
brenno deleted branch feat/beveiligingsharding 2026-07-22 11:38:56 +00:00
Sign in to join this conversation.
No description provided.