fix(security): re-review follow-ups — drop HEIC/HEIF, fix stale comment
Address the two items from the adversarial re-review of batch-2. - upload: remove image/heic + image/heif from ALLOWED_MEDIA. Neither the `image` crate nor the bundled ffmpeg 6.1 (Alpine 3.21 — HEIF demuxer only landed in ffmpeg 7.0) can decode them, so accepting them stored posts that never got a thumbnail. iOS Safari transcodes HEIC->JPEG on file-input selection, so this rejects only the rare HEIC-preserving path, now with a clear error instead of a silently broken post. - data-mode-store: correct the stale "auth-gated" comment — the /original route is intentionally unauthenticated (UUID-as-capability) so it works from plain <img src> / <video src>. Re-verified: cargo build (only the pre-existing middleware.rs warning). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,13 +21,17 @@ const MAX_CAPTION_LENGTH: usize = 2000;
|
|||||||
/// we trust, store, and hand to the compression pipeline — so a text-based payload
|
/// we trust, store, and hand to the compression pipeline — so a text-based payload
|
||||||
/// (SVG/HTML/JS) can never be stored or served on-origin. Each entry maps to the
|
/// (SVG/HTML/JS) can never be stored or served on-origin. Each entry maps to the
|
||||||
/// server-controlled file extension we persist the original under.
|
/// server-controlled file extension we persist the original under.
|
||||||
|
///
|
||||||
|
/// HEIC/HEIF are deliberately excluded: the preview pipeline (`image` crate, and
|
||||||
|
/// the bundled ffmpeg 6.1) cannot decode them, so accepting them would store files
|
||||||
|
/// that never get a thumbnail. iOS Safari already transcodes HEIC→JPEG when a photo
|
||||||
|
/// is selected via a file input, so this rejects only the rare HEIC-preserving
|
||||||
|
/// upload path — with a clear error rather than a silently broken post.
|
||||||
const ALLOWED_MEDIA: &[(&str, &str)] = &[
|
const ALLOWED_MEDIA: &[(&str, &str)] = &[
|
||||||
("image/jpeg", "jpg"),
|
("image/jpeg", "jpg"),
|
||||||
("image/png", "png"),
|
("image/png", "png"),
|
||||||
("image/webp", "webp"),
|
("image/webp", "webp"),
|
||||||
("image/gif", "gif"),
|
("image/gif", "gif"),
|
||||||
("image/heic", "heic"),
|
|
||||||
("image/heif", "heif"),
|
|
||||||
("video/mp4", "mp4"),
|
("video/mp4", "mp4"),
|
||||||
("video/quicktime", "mov"),
|
("video/quicktime", "mov"),
|
||||||
("video/webm", "webm"),
|
("video/webm", "webm"),
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// Per-device "Datenmodus" — Saver loads compressed previews (default), Original loads
|
// Per-device "Datenmodus" — Saver loads compressed previews (default), Original loads
|
||||||
// the full file via the auth-gated `/api/v1/upload/{id}/original` endpoint.
|
// the full file via the `/api/v1/upload/{id}/original` endpoint. That route is
|
||||||
|
// intentionally unauthenticated (the UUID acts as the capability) so it works from
|
||||||
|
// plain `<img src>` / `<video src>` without an Authorization header.
|
||||||
//
|
//
|
||||||
// Stored per-device in localStorage (not per-user) because data plans are a property
|
// Stored per-device in localStorage (not per-user) because data plans are a property
|
||||||
// of the device the guest is currently holding, not their identity.
|
// of the device the guest is currently holding, not their identity.
|
||||||
|
|||||||
Reference in New Issue
Block a user