Security
How we protect your secrets - and why we genuinely cannot read them.
The short version
Your secret is encrypted in your browser before it leaves your device. We store only the encrypted result - a scrambled blob of data that is meaningless without the key. The key never comes to us. Even if our entire database were stolen, your secrets would be unreadable.
This is called zero-knowledge encryption. It means we have zero knowledge of what you are sharing.
How a secret travels
Here is exactly what happens when you create and share a secret:
Your text exists only in your browser tab. Nothing has left your device yet.
256 bits of randomness, created by your browser's built-in cryptography. This key never leaves your browser.
Using AES-256-GCM - the same standard used by banks and governments. The result is an unreadable blob of data.
We receive and store ciphertext only. Your plaintext and your key never travel to us.
In standard mode, your share link looks like
disposablesecret.com/view/AbCdEfGh#key. The part after # is the key. Browsers never include the # fragment in requests to servers - so even as you share the link, the key never touches our systems. In passphrase mode there is no fragment - the key is derived from your passphrase in the recipient's browser instead.
When the recipient opens the link, their browser fetches the encrypted blob from our server and decrypts it locally - using the key from the
# fragment in standard mode, or by deriving the key from their passphrase in passphrase mode. Our server immediately and permanently destroys the stored blob.
Passphrase protection
When you add a passphrase, the process is slightly different. Instead of a random key, your browser derives an encryption key from your passphrase using PBKDF2 (200,000 iterations with SHA-256 and a unique random salt). This is a standard technique for turning a human-memorable passphrase into a strong cryptographic key.
The salt is stored alongside the encrypted secret so the recipient's browser can derive the same key. The passphrase itself travels to our server only once - to let us verify the recipient knows it before handing over the ciphertext. We hash it immediately with Argon2id (a modern, memory-hard algorithm) and discard the original. We store only the hash, which cannot be used to decrypt anything.
We recommend sending the link one way and the passphrase another - for example, the link by email and the passphrase by text message.
The one deliberate exception
If you choose to receive an email notification when your secret is viewed, we need to store your email address until the secret is viewed. This is the one case where our server holds something sensitive, which is exactly why we encrypt it with our key before storing it - so even at rest it is unreadable without us actively decrypting it to send your notification. We delete it the moment that notification is sent. We document this exception openly because you deserve to know, and unlike other platforms, this is the only thing we hold that we could ever be compelled to produce.
We also record the approximate location (city and country) of the viewer using a local database lookup. No IP address is stored at any point - the lookup is performed and the IP address immediately discarded.
What we store vs what we cannot access
| What is stored | Can we read it? | When is it deleted? |
|---|---|---|
| The encrypted secret payload | No - encrypted with a key we never have | Immediately on viewing, or after 24 hours |
| Argon2 passphrase hash (if used) | No - a one-way hash only | Immediately on viewing, or after 24 hours |
| Notification email (if provided) | Yes - encrypted with our key, decrypted to send | Immediately after notification is sent |
| Approximate viewer location | Yes - city and country only, no IP | Retained as metadata on the secret record |
| Secret creation timestamp | Yes - standard metadata | Retained as metadata on the secret record |
Verify it yourself
We believe you should not have to take our word for any of this. The encryption happens in your browser, which means you can inspect it directly.
How to check
- Open the homepage in your browser.
- Open your browser's developer tools (F12 or right-click → Inspect).
- Go to the Network tab and tick Preserve log.
- Type a secret and click Generate Link.
- Find the
POSTrequest to/share/and click on it. - Look at the Payload or Form Data section.
You will see a secret field containing a long string of random-looking characters -
that is the AES-256-GCM ciphertext. You will not see your original text anywhere in the request.
In standard mode, a fragment_key field will also be present - this is the
encryption key, appended to the URL client-side after the redirect and never sent to our
server in any subsequent request. In passphrase mode this field will not appear, as the
key is derived from the passphrase in the recipient's browser rather than embedded in the URL.
Reading the source
The encryption code lives in /assets/js/share.js on this server. You can
view it directly at
https://disposablesecret.com/assets/js/share.js.
The key functions to look for are generateRandomKey(), aesGcmEncrypt(),
and the form submit handler that replaces your plaintext with ciphertext before the POST fires.
The decryption code lives in /assets/js/view.js, available at
https://disposablesecret.com/assets/js/view.js.
Look for importRawKey() and decryptBlob() - these run entirely in
the recipient's browser using the key from the URL fragment.
Responsible disclosure
If you discover a security vulnerability, please report it to us privately before disclosing it publicly. We take all reports seriously and will respond promptly.
Contact us at [email protected] with details of the issue.
See also: Privacy Policy • Terms of Service • About