once
← create a secret

security

Designed so stored secrets are unreadable to the server.

once combines browser-side encryption, two independent unlock pieces, short retention, and atomic deletion. Here is the exact boundary—and where it ends.

Last updated · 11 August 2026

The protocol

  1. 01

    Derive separate keys

    Argon2id strengthens the password. HKDF then creates domain-separated content and proof keys.

  2. 02

    Seal locally

    AES-256-GCM encrypts and authenticates the text inside the sender's browser before upload.

  3. 03

    Split what unlocks it

    The password is shared separately. A random link secret stays after the URL #, which browsers do not send in HTTP requests.

  4. 04

    Delete before reveal

    One atomic database statement validates the protected proof, deletes the row, and returns it to exactly one successful reader.

What the server stores

The live record contains a random identifier, ciphertext, nonce, salt, KDF parameters, HMAC-protected proof, protocol version, creation time, and expiry. It does not contain the plaintext, password, or URL-fragment link secret. Proof material is protected with a server-side HMAC before database storage, so a database dump alone does not provide a usable offline password check.

Secret pages and API responses use no-store caching, the global referrer policy is no-referrer, and secret routes are excluded from search indexing. A nonce-based Content Security Policy restricts scripts, connections, frames, forms, fonts, and images to the minimum the application needs.

What this protects against

  • A copied database does not contain readable secret text or the fragment link secret.
  • Someone with only the private link or only the password is missing an unlock factor.
  • Concurrent valid reveals have one database winner rather than two readable copies.
  • Wrong passwords do not consume the note and repeated attempts trigger a cooldown.
  • Expiration limits how long an unopened encrypted record remains live.

Honest limits

  • A compromised sender or recipient device, browser, extension, clipboard, or password manager can expose plaintext.
  • A recipient can copy, photograph, forward, or otherwise retain a secret after reveal.
  • A weak password is easier to guess. Argon2id increases the cost; it cannot make a poor password strong.
  • The link fragment is hidden from ordinary HTTP requests, but it can still leak through screenshots, messages, browser extensions, malware, or careless sharing.
  • Like any hosted web app, a malicious or compromised future application build could change client code. Verify the domain and HTTPS connection before entering a secret.
  • once has not claimed an independent security audit, formal certification, or bug bounty program.

Report a vulnerability

Email me@asabbagh.com with a clear description, affected URL or component, reproduction steps, impact, and a safe proof of concept. Minimize sensitive information in the first message and never include another person's secret, password, or private link.

  • Test only with notes and data that you control.
  • Do not access, alter, retain, or disclose another person's data.
  • Do not use denial-of-service, high-volume automation, spam, or social engineering.
  • Allow a reasonable opportunity to investigate and fix the issue before publication.

There is no guaranteed response time or payment. Good-faith reports that respect these boundaries are welcome. Automated discovery is available at /.well-known/security.txt.