Strypt: a metadata stripper in Rust (library, CLI and egui desktop app)

strypt removes identifying metadata (GPS, camera serials, author names, edit history) from JPEG, PNG, WebP, TIFF, GIF, HEIF/AVIF, SVG, JPEG XL, PDF, OOXML, ODF, FLAC, WAV, MP3, Ogg and MP4. It's a library, a CLI, and as of 0.2.0 a desktop app, all calling the same core.

Repo: https://github.com/FadeHack/strypt
Crates: strypt (CLI, cargo install strypt) and strypt-core (the library both front-ends call)

Some design choices that might interest people here:

  • All logic in strypt-core, which returns structured data and has no CLI dependencies. Typed errors with thiserror, so callers can tell unsupported from corrupt from I/O.
  • #![forbid(unsafe_code)], and no unwrap/indexing/unchecked arithmetic on the parsing path. Malformed input is expected input.
  • No network, enforced on the dependency graph. CI fails if any crate in the tree, transitive ones included, can open a socket, and the check is proven to fail when violated.
  • The GUI is eframe/egui, not Tauri, because Tauri pulled an HTTP client into the graph and needs WebKit2GTK on Linux.
  • Fail closed. Each stripped file is re-inspected, and discarded if anything the handler recognises survived.
  • Fuzzing: one cargo-fuzz target per handler, a minute each on every push plus 24-hour local batches judged by a coverage-curve rule.
  • Reproducible release builds, with GitHub attestations and CycloneDX SBOMs.

Per-format decisions are written up as ADRs in docs/DECISIONS.md, e.g. why TIFF and HEIF are rebuilt while MP4 is edited in place with its chunk offsets remapped.

Code review is very welcome, especially on the parsers in crates/strypt-core/src/formats/ and container/. If you find metadata surviving a strip, please report it privately via SECURITY.md.