DEV Community

jaryn
jaryn

Posted on

Reject Image Polyglots After EXIF Removal, Before They Reach Your CDN

Removing EXIF GPS protects one privacy boundary. It does not prove that an uploaded JPEG contains only a JPEG.

A useful hostile fixture is a valid image followed by bytes for another format. Many decoders stop at JPEG’s end marker and display the picture successfully, while downstream scanners, content sniffers, or accidental downloads may interpret the trailing payload differently.

Build a fixture set rather than trusting extensions:

clean.jpg                  valid JPEG
exif-gps.jpg               valid JPEG with location
jpeg-plus-zip.jpg          JPEG followed by ZIP bytes
jpeg-plus-html.jpg         JPEG followed by HTML
truncated.jpg              missing end marker
oversized-dimensions.jpg   small file, dangerous decode cost
Enter fullscreen mode Exit fullscreen mode

My upload gate has independent layers:

  1. Store the original in a non-public quarantine location.
  2. Enforce byte-size and decoded-dimension limits.
  3. Decode with a maintained image library.
  4. Re-encode pixels into a new file, discarding metadata and trailing bytes.
  5. Verify the output’s signature, dimensions, and complete parse.
  6. Publish only the derived object under a server-generated name.

A boundary check can detect bytes after the end marker, but re-encoding is the stronger transformation because it creates a new representation from decoded pixels. Keep the original inaccessible and delete it according to a tested lifecycle.

assert(outputSize <= limit);
assert(decoded.width * decoded.height <= pixelBudget);
assert(parseConsumesEntireFile(output));
assert(noLocationMetadata(output));
Enter fullscreen mode Exit fullscreen mode

The OWASP File Upload Cheat Sheet recommends defense in depth: allowlisted types, generated filenames, size limits, storage separation, and content validation. No single MIME header or metadata scrubber replaces that chain.

The important privacy lesson is broader than EXIF: inspect every representation that survives the upload pipeline, and publish only a constrained derivative.

Top comments (0)