Removes the information a file carries about you, and tells you exactly what it found.
Photographs and documents hold a second payload that has nothing to do with what they look like: GPS coordinates, camera serial numbers, the author's real name, the editing-session identifiers that link two documents to one machine. Sending a file sends all of it.
Status: working, not yet released. Desktop application and command line tool, 173 tests, 20,000 fuzz cases with no panics. No installer or icon yet, and no signed builds.
It rebuilds files rather than editing them. Deleting the metadata you recognise leaves everything you do not: a vendor's private segment, a new chunk type, a blob appended after the end-of-image marker. Each parser here walks the input and copies across only what is on an explicit keep-list, so anything unknown is dropped for not being on it. A 25 MB photograph from a Fujifilm camera turned out to carry 39 kB of undocumented vendor data that a denylist tool would have passed straight through.
It says when it could not help. A format it cannot take apart is reported as such and returned untouched, and no output file is written. Claiming success on a file nobody understood is the failure that actually harms someone.
It separates what is provable from what is not. Metadata removal is verifiable: the bytes are in defined places and they are gone. Reducing a camera sensor's fingerprint is statistical, so it lives in a different crate, behind a setting that is off by default, reported in different words.
| Format | Approach | Assurance |
|---|---|---|
| JPEG, PNG, WebP, HEIF, AVIF | Container rebuilt from a keep-list | Complete |
| GIF | Block stream rebuilt from a keep-list; animation kept | Complete |
| TIFF | Each directory rebuilt from a keep-list; pixels copied verbatim; multi-page kept | Complete |
| SVG | Metadata, editor fields, scripts and external references removed | Best effort |
| XMP sidecar (.xmp) | Rebuilt as an empty packet; nothing it held survives | Complete |
| Object graph rebuilt | Best effort | |
| Word, Excel, PowerPoint, OpenDocument | Archive parts cleaned, images inside recursed | Best effort |
| Camera raw (DNG, CR2, CR3, NEF, NRW, ARW, SR2, RW2, ORF, RAF, PEF, SRW, ERF, GPR, IIQ, MOS, 3FR, …) | Cleaned in place, never rebuilt. Removed: GPS, timestamps, owner/artist, XMP/IPTC, standard serial and image-ID fields, and the embedded preview's own EXIF. Kept: make/model and the vendor maker note. Untouched: the sensor data and decodability | Best effort |
| Sigma X3F raw | Recognised but returned untouched, reported as not cleaned | None |
| Video (MP4, MOV, MKV, WebM, AVI) | Recognised and named, but not cleaned yet; reported honestly with what videos leak (GPS, device, time) so it is never mistaken for clean | None |
| Audio (MP3, M4A, FLAC, OGG, WAV) | Recognised and named, not cleaned yet, reported honestly | None |
| Anything else | Returned untouched, reported as not cleaned | None |
A photo saved as a Motion Photo / Live Photo carries a whole short video after its end marker. Cleaning the photo drops that video (it is trailing data), and metascrub now reports it specifically rather than as anonymous bytes, so you know the clip and its own location and time were there and are gone.
A camera raw is the sensor's near-unprocessed readout, not a picture — a straight-from-the-camera JPEG is not a raw. Raws cannot be rebuilt from an allowlist without corrupting the undocumented vendor sub-sections that hold the actual sensor image (verified against real files from many brands), so they are cleaned by careful in-place editing that never moves a byte. The maker note is deliberately kept: manufacturers store the parameters a raw converter needs to develop the file in the same block as the serial number, and removing it broke real files. So a raw's internal serial number usually survives. To remove that too — and to get a Complete clean — develop the raw into a JPEG or PNG first and clean that. The desktop app's reference panel explains exactly what changes and what does not, and how it differs by camera brand.
Desktop. Drag files onto the window. It lists what it found in each one, and writes cleaned copies only when you ask. Originals are never modified.
Command line.
metascrub -n photo.jpg # report only, write nothing
metascrub photo.jpg # writes photo.clean.jpg
metascrub --json *.jpg # machine-readableExit status 2 means a file was left uncleaned because its format is not
supported, so a script cannot mistake "not understood" for success.
cargo build --release
cargo test --workspaceNo system dependencies. The toolchain is pinned in rust-toolchain.toml.
| Crate | What it is |
|---|---|
metascrub |
The library. No interface, no image decoding, no dependency on the others. |
pixelwash |
Sensor-fingerprint reduction. Separate because it decodes images. |
metascrub-gui |
Desktop interface. |
metascrub is usable on its own and is meant to be: it exists partly to be
embedded in other applications that need to clean a file before sending it.
- It cannot make an upload anonymous. Cleaning handles what is inside the file. If you upload while logged in, the platform has its own record of which account sent what and when.
- It cannot remove a sensor fingerprint, only reduce how well it matches.
- It cannot help with a format it does not understand, and it will say so rather than pretend.
The application explains all of this at length, including several widely repeated pieces of advice that are wrong.
See SECURITY.md for how to report an issue, and for what is
explicitly not a vulnerability.
GPL-3.0-or-later.