Sharing secrets with a link (fragment-based)

Published: 2026-09-05

How URL hash fragments keep ciphertext off server logs, how AES-GCM plus a password seals a shareable link, and what fragment-based secret sharing can and cannot guarantee.

Handing someone an API key or one-off password over chat is risky: the plaintext sits in message history, search indexes, and device backups. Fragment-based secret sharing encrypts the content in the browser, packs ciphertext into the URL hash (the part after #), and lets the recipient decrypt locally with a master password. The hosting server never needs to store the note—and typically never even sees the ciphertext when the page loads.

This guide explains why fragments matter, how a sealed link is built, how to share the password safely, and which threats this model does not solve.

Query string vs fragment: what the server sees

A URL has several pieces. For sharing, the important split is:

Part Example Sent to the server on navigation?
Path + query /secret-share?token=abc Yes — appears in access logs, CDN logs, Referer in some setups
Fragment (hash) /secret-share#ls1.… No — browsers keep #… client-side; it is not included in the HTTP request

That is why LocalTools’ Secret Share puts the sealed payload only after #. Loading /secret-share#… fetches the static page; your browser then reads location.hash and decrypts in-tab. Next.js API routes never receive the plaintext, password, or ciphertext from that fragment.

Contrast this with “pastebin” or “burn-after-read” services that upload ciphertext (or worse, plaintext) to a database. Those can offer expiry and audit trails, but they introduce server storage and a trust surface. Fragment-based links trade server features for no server copy.

For the broader privacy model, see Why “local only” matters for developer tools.

What goes into a sealed link

Under the hood, a typical local seal does three things:

  1. Derive a key from your master password (LocalTools uses PBKDF2-SHA256, 100,000 iterations, with a fresh random salt).
  2. Encrypt the UTF-8 secret with AES-GCM (256-bit key, fresh 12-byte IV/nonce).
  3. Encode salt, IV, and ciphertext (including the GCM authentication tag) as Base64URL parts in the fragment.

Payload shape used by Secret Share:

#ls1.<salt>.<iv>.<ciphertext>
  • ls1 — version marker so future formats can coexist.
  • Salt — 16 random bytes; different seals with the same password do not share a key.
  • IV — 12 random bytes; never reused under the derived key for that seal.
  • Ciphertext — AES-GCM output (ciphertext ‖ tag).

Wrong password or a truncated/corrupted fragment fails decryption instead of returning garbage—thanks to GCM’s tag check. For the crypto pieces in plain language, see AES-GCM basics (nonce, tag, AAD) and HKDF vs PBKDF2 in plain language. Encoding choices for binary payloads are covered in Base64 vs hex: representing bytes.

Dual-channel sharing (link ≠ password)

A sealed URL alone is not enough if the master password is weak or travels in the same message as the link. Prefer:

Channel What to send Why
Chat / email / ticket The encrypted link Safe to log if the password stays out
Call / Signal / password manager share / in person The master password Out-of-band so a single leak does not decrypt

If both land in the same Slack thread, anyone with channel access can decrypt. Treat the password like any other secret: generate something strong (see Generating passwords and tokens in the browser and Password strength beyond “8 characters”), and do not reuse it across unrelated seals.

What “no expiry” really means

Because nothing is stored on a server, there is no delete button on the vendor’s side and no TTL enforced by a database. The link “never expires” in the sense that anyone who still has the exact URL and the password can decrypt forever—unless you rotate the underlying secret (revoke the API key, change the password you shared).

That is a feature for offline handoffs and a limitation for “burn after read.” If you need guaranteed one-time retrieval or admin revocation, you need a service that stores ciphertext and enforces policy—with the trust trade-offs that implies.

Practical hygiene:

  • Prefer short-lived credentials when the recipient can rotate them after first use.
  • After they confirm receipt, revoke or rotate the shared secret when possible.
  • Avoid putting sealed links in public repos, screenshots, or issue trackers that archive forever.

Threats this model does not remove

Risk Why it still matters
Browser history / bookmarks The full URL including #… is often saved locally
Chat clients that expand previews Some apps fetch URLs; fragment handling varies—prefer tools that do not strip privacy, and still use a strong password
Shoulder surfing / screen share Ciphertext is opaque; the decrypted plaintext on screen is not
Compromised device Malware or a malicious extension can read the page after unlock
Weak password Offline guessing against the fragment is possible if someone has the link
Copy/paste mistakes Pasting plaintext into the wrong channel bypasses encryption entirely

Also remember: HTTPS protects the path request in transit; the fragment never leaves the browser for that navigation, but once the recipient decrypts, the plaintext lives in memory and on screen like any other note.

When fragment-based sharing fits

Good fits:

  • Handing a teammate a staging API key without pasting it into chat history
  • One-off onboarding secrets where you can also send the password out-of-band
  • Avoiding “upload this secret to our paste service” for compliance-sensitive teams

Poor fits:

  • Secrets that must auto-expire or be revoked centrally
  • Very large blobs (URL length limits; stick to short text)
  • Recipients who cannot open a modern browser with Web Crypto

Try it locally

Use Secret Share to:

  1. Paste a short secret and choose a strong master password.
  2. Seal & generate a link; confirm the payload lives only after #.
  3. Open the link in a private window, decrypt with the same password, then try a wrong password and confirm it fails.

Related reading: Why “local only” matters for developer tools, AES-GCM basics (nonce, tag, AAD), HKDF vs PBKDF2 in plain language, and Generating passwords and tokens in the browser.

All learn articles