How this site is protected
A security tool that is not secure has no right to exist. This page explains what we do and, more importantly, how to check it without taking our word for anything.
Last updated:
The design is the first defence
The most important security decision in this project is that there is no backend. With no upload endpoint there are no malicious files to process; with no database there is no data to leak; with no accounts there are no sessions to steal and no passwords to lose. Whole categories of the OWASP Top 10 are not mitigated here — they simply do not apply.
Content-Security-Policy
The policy starts at default-src none, which forces every capability to be granted explicitly: nothing slips in by omission. There is no unsafe-inline in any directive, for scripts or styles, which shapes how the code is written and is worth it.
The line doing the heaviest lifting is connect-src, which permits only this domain, the breached-password API and our own visit counter. If a compromised dependency tried to send your photo or your password anywhere else, the browser would refuse the request. That is genuine defence in depth: the protection does not depend on our code behaving.
The supply chain is the main risk
If all the cryptography runs in your browser, a malicious third-party package could read what you type. That is the vector that actually matters, which is why:
- There is a dependency budget. Every new one needs justifying; under a hundred lines and we write it by hand.
- Package install scripts are disabled — the cheapest route to compromising a developer machine.
- There are no third-party resources at runtime: the fonts, the icons and even the program that counts visits are hosted here. Zero external CDNs, and no foreign domain can execute code on this site.
- Versions are pinned in the lockfile and installs are reproducible.
- A verification script breaks the build if innerHTML, eval, new Function or Math.random appear in the source.
Cryptography
We have written no cryptography. It is all WebCrypto primitives from the browser itself: AES-256-GCM to encrypt, PBKDF2-SHA256 with 600,000 iterations to derive the key, and a fresh random salt and initialisation vector for every message. The message format carries its own version, with the iteration count travelling inside each message, so the parameters can be raised later without orphaning messages already sent. A tampered message does not decrypt: it fails the GCM integrity check.
File handling
- Format is determined from the file's actual bytes, never from its extension or the type the browser reports: both are attacker-controlled.
- Parsing happens in an isolated Web Worker. If a malformed file causes a crash, the worker dies and the page stays alive.
- There is a size limit and a processing timeout, so a file designed to burn resources cannot freeze the tab.
- Your original file is never modified: a clean copy is produced.
Responsible disclosure
If you find a flaw, tell us. We are especially interested in anything that would cause a person's data to leave their browser. Contact details are in /.well-known/security.txt and we commit to responding within 72 hours. There is no bounty programme yet, but there is public credit if you want it.