DEV Community

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

The Problem with EXIF-Only Checks

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.

Testing with a Fixture Set

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

Recommended Upload Pipeline

My upload gate has independent layers:

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

Boundary Checks and Re-encoding

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.

Verification Assertions

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

Defense in Depth

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.

Comments

No comments yet. Start the discussion.