Client-side encryption protects a stored secret from the operator and from anyone who obtains the database, and nothing else: malicious JavaScript, a browser extension or a leaked link defeats it, because the key travels in the link. It is not a silver bullet, and it charges for its one guarantee in other places.
This guide explains what browser-side encryption guarantees, where it quietly breaks down, how it compares with the server-side model, and how LinkPilot combines the two since 29 September 2026, when its one-time secret link generator moved to encrypting in the browser.
Rewritten 19 October 2026. The original version of this article described LinkPilot's then-current server-side model; a note added on 29 September 2026 recorded the switch. This version describes the current model throughout. The reasoning about what each model does and does not protect is unchanged.
What does client-side encryption actually protect?
The stored secret, from the operator and from anyone who obtains the database. In a client-side encrypted secret tool (also called end-to-end encrypted, or E2EE), the workflow is:
- The browser generates a symmetric key, typically a 256-bit
AES-GCM key via the
Web Crypto API
(
crypto.subtle.generateKey). - The payload is encrypted in the browser with that key.
- Only the ciphertext is sent to the server, which stores it under a random identifier.
- The key is appended to the share link as a fragment (
#…). Per RFC 3986, section 3.5, browsers never send the fragment in HTTP requests, so the key does not cross the wire to the server. - The recipient's browser reads the fragment, fetches the ciphertext, and decrypts locally.
The server only ever sees ciphertext. An operator reading its own database, a database backup that leaks, a subpoena for stored data: none of them yields the secret, provided every other link in the chain holds.
Anatomy of an E2EE secret link
https://example.com/s/x7Kd93hF2a#4fT9wLm2...Qz1
└──────── sent to the server ───┘└ browser only ┘
Everything before the # travels in the request and can appear in
server and proxy logs. The fragment is processed only by the
recipient's browser. That one character does all of the security
work, which is elegant, and also the root of most of the failure
modes below.
What does client-side encryption not protect against?
Malicious or compromised JavaScript, browser extensions, and a leaked link, because the key is in the link.
- It does not protect against malicious JavaScript. The encryption code runs in the browser, and the browser got that code from the server. If the server delivers altered code, because the operator turned malicious, was compelled, or was hacked, the secret can be read before encryption or after decryption. This is the fundamental limit of browser-based E2EE.
- It does not protect against browser extensions. An extension with page access sees the plaintext after decryption and can read the fragment directly.
- It does not make a leaked link harmless. The key is part of the link. If the recipient pastes the full link into chat, forwards the email, or has browser history sync on, the key travels with it. An E2EE link with a leaked URL is a fully readable secret. A passphrase sent by another channel is the only defence, which is why LinkPilot mixes the passphrase into the key rather than checking it separately.
- It does not audit, scan or preview content. Because the server cannot read the payload, it cannot do content filtering, malware scanning or data-loss prevention on it. Controls have to work on the ciphertext and on access events instead.
The code-delivery problem, spelled out
The point worth sitting with: browser E2EE means trusting the server you supposedly do not trust to deliver honest JavaScript on every page load. A native app is installed once, signed and versioned; a web page is re-fetched every visit. Subresource integrity and published source code narrow the gap without closing it.
So the honest reading of "we cannot read your secrets" is "we cannot read your secrets passively". Turning a passive capability into an active attack that ships modified code is a real upgrade (active attacks are riskier, targeted and potentially detectable), but it is not the same as "impossible". That applies to LinkPilot's claim as much as to anyone else's.
The server-side alternative
The other common design, and the one LinkPilot used until September 2026, encrypts at rest on the server and protects the reveal with a hashed passphrase:
- TLS in transit; payloads stored in a dedicated table on a database with disk-level encryption at rest.
- Passphrases hashed in the browser before transport and compared by hash; the raw passphrase never reaches the database.
- Destructive burn: on first reveal, expiry or revocation the stored payload is overwritten and later attempts get HTTP 410.
- Passphrase attempts rate-limited and logged.
The server can read an active secret in this model. That is what makes server-side preview, scanning and content-aware features possible, and it is exactly the property E2EE removes. Open-source tools such as OneTimeSecret still use it; is OneTimeSecret safe? looks at the consequences.
What LinkPilot does now
Since 29 September 2026, LinkPilot uses client-side encryption and keeps the server-side controls that do not need the content. From the security architecture page:
- Encryption in the browser. The payload is encrypted with AES-GCM-256 using a 256-bit key generated in the sender's browser. The server stores the ciphertext and nothing else; the key travels in the fragment of the share link.
- Passphrase as part of the key (Pro). A passphrase is stretched with PBKDF2-SHA256 (210,000 iterations) and combined with the link key through HKDF-SHA256, so neither the link alone nor the passphrase alone decrypts the secret. Attempts are rate-limited to 5 per IP per minute per secret, across an in-memory limiter and a database-backed sliding window.
- Burn-after-read on the ciphertext. The view is recorded
atomically through a database function, so concurrent reveal
attempts cannot leak the secret twice; the stored ciphertext is
overwritten with
[REDACTED]and later attempts return HTTP 410. - Revocation. A secret can be revoked from the dashboard at any time; revoked secrets refuse to reveal and return 410.
- Preview-safe reveal. Link unfurlers and email scanners issue GET requests, which return metadata only (status, whether a passphrase is required). A view is recorded only on an explicit reveal from a browser.
- Audit timeline (Pro). Created, viewed, failed passphrase, burned, expired and revoked, each with a timestamp, the country and city the edge reports, the browser string and a daily-salted hash of the address. The timeline records access, never content.
- Files. Attachments are encrypted in the browser too, with a key derived from the link key. A file's name, size and type remain visible to LinkPilot as metadata.
Three limits, stated plainly. Secrets created before 29 September 2026 were stored as plaintext until they expired; they were never rewritten. File metadata is visible even though file contents are not. And everything in the "what it does not do" section applies: malicious JavaScript, browser extensions and a leaked link are not solved by this model or any other browser-based one.
Trade-off summary
| Concern | Client-side E2EE (pure) | Server-side + hashed passphrase | LinkPilot since Sept 2026 |
|---|---|---|---|
| Operator reads stored secrets (passive) | Mitigated | Trust required | Mitigated: ciphertext only, no key |
| Operator serves malicious JavaScript | Not mitigated | Not mitigated | Not mitigated |
| Compromised JS / supply chain | Not mitigated | Not mitigated | Not mitigated |
| Attacker with a database dump | Mitigated (ciphertext) | Mitigated by encryption at rest; burned payloads already redacted | Mitigated (ciphertext; burned payloads redacted) |
| Leaked link, no passphrase | Readable: the key is in the link | Readable until burn or expiry | Readable until burn or expiry; short expiry is the control |
| Leaked link, with passphrase | Depends on the tool | Protected by the hash check | Protected: the passphrase is part of the key (Pro) |
| Link preview or scanner opens the link | Depends on the tool | Depends on the tool | GET returns metadata only; no reveal |
| Audit log | Access events only | Full lifecycle | Full lifecycle, from access events (Pro) |
| Server-side content scanning / DLP | None | Possible | None |
| Admin and team visibility | None | Configurable | Workspace roles, timeline, revocation; no content |
No model is "more secure" in the abstract. They defend different threats at different costs, and combining them narrows the set of things you give up rather than eliminating it.
Matching the model to the threat: three scenarios
1. Sending a contractor a database password. The threat is the secret lingering in email or chat, or a stray forward. Any model handles it with a short expiry and burn-after-read; the deciding factors are usability and the record. Browser-side encryption with a passphrase sent out of band, and a timeline that shows when the link was opened, is the pragmatic pick.
2. A journalist receiving material from a source. The threat model includes the platform operator being compelled to disclose. Here the operator is part of the threat, so E2EE is a minimum, and purpose-built tools such as SecureDrop, where the whole system is designed around that threat, are the right call. A web tool that could be compelled to serve altered JavaScript is not enough on its own.
3. An engineering team doing routine credential hand-offs. The threat is sprawl: forgotten links, no record of who saw what. The features that matter are the timeline, revocation, workspace roles and an expiry policy. Those used to require a server that could read the content; they do not any more, because they act on ciphertext and access events. Secure password sharing for teams is the policy side of this scenario.
How to choose
Pick client-side encryption when:
- You do not trust the operator, including yourself running on cloud infrastructure you cannot fully verify.
- Regulatory or contractual rules require that the provider be technically unable to read the content.
- You will send the passphrase by a second channel and keep expiry short, because a leaked link is otherwise the whole secret.
Pick server-side encryption when:
- You need the server to inspect content: malware scanning, data-loss prevention, content filtering.
- You are self-hosting a single-purpose tool and the operator is you.
Look for both when:
- You want the operator out of the trust chain and still need a timeline, revocation, team roles and a reveal that a link preview cannot trigger. Ask the vendor which controls work on ciphertext and which quietly need plaintext.
When not to use either
Some secrets should not travel through any sharing link. Long-lived root credentials, production signing keys and bulk data exports belong in a secrets manager or KMS with access control, not in a URL. And if the recipient needs the value repeatedly, a password manager vault item beats re-sending links; one-time delivery is for hand-offs, not storage. Secret links vs password managers draws that line.
Verifying a claim
Do not pick a tool by which one claims more. Pick by what you are defending against, and check that the claim on the tin matches the architecture underneath:
- Is the key in the fragment? Open the link's structure; the key
should be after the
#. - Does a plain fetch of the link return the secret? It should not.
- What does the passphrase do: gate the reveal, or form part of the key?
- What is logged, and does the operator say so in writing?
LinkPilot's answers are on the security architecture page, including the limits. The same test applies to that page as to anyone else's.
Related reading
- How one-time secret links work
- Is OneTimeSecret safe?
- LinkPilot vs PrivateBin
- Secret links vs password managers
- Why URLs leak sensitive information
- Link scanners and one-time secrets
References
- W3C, Web Cryptography API.
- NIST, SP 800-38D: Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC.
- IETF, RFC 3986, section 3.5 Fragment.
- Freedom of the Press Foundation, SecureDrop.