mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-30 05:16:56 -06:00
Image entries applied bytes to any key with no checks (audit COL-9): a collaborator could poison the shared content-addressed image store, claim absurd dimensions, balloon memory, or name an image `../../x`, which a saved file then wrote as the archive member `images/../../x`. - Every key must be 1–128 ASCII letters, digits, `-` or `_`: `figcraft_doc::ImageData::is_valid_key`, promoted from the format crate's private `is_valid_hash` so the file reader and collab share one rule. The reader now also takes `-` and `_`, so the REST importer's `rest-image-missing` placeholder survives a save and load. - The REST importer's side of the same attack: an unresolved `imageRef` that can't legitimately be an archive member name (path text, an over-long ref) shares the `rest-image-missing` placeholder instead of being keyed by its raw name (`image_tests::a_path_like_rest_image_ref_never_names_an_archive_member`). - A key with the shape of a content hash (64 hex chars) must be exactly the lowercase sha256 of the bytes, the form `image_hash` writes; an uppercase look-alike is refused. Other keys (svg FNV-128, REST placeholders) claim no content address and only meet the rules above. - A side is at most 65 535 px; decoded bytes at most 32 MiB, with the base64 text capped before decoding. 0×0 stays valid: the format crate stores it for sizes it can't probe. - Refusals are Error::Invalid and reject their batch, so every replica's store stays clean; catch-up snapshots apply through the same check. - Docs: collab-protocol.md, collaboration-parity.md and file-format-parity.md (rows, status lines, histories). - Tests: collab image_tests (8), format image_tests: round-trip and the REST placeholder gate.