Featured workCase file
Developer tool / one-time secret bridge
shh
open sourceA family errand needed a gift-certificate link pulled out of a chat transcript, and the obvious answers — paste the secret into the chat, or trust redaction to clean it up later — were both wrong. shh is the one-time bridge that grew out of that moment.
The task sounded small: pull the gift-certificate link for a planned outing out of a conversation and hand it to the agent. The problem was structural. The link was bearer-like credential material, and the natural ways to move it — pasting it into the chat or letting transcript redaction tidy it up afterward — put plaintext where it did not need to exist in the first place.
shh is the deliberate alternative: an open-source, MIT-licensed, self-hostable one-time secret bridge. It moves values between a human and an AI agent in both directions while keeping plaintext out of chat and model context. The hosted instance at shh.qcfailed.com is a best-effort public demo with no account or SLA; serious installations can self-host.
- Two directions: Human → Agent and Agent → Human
- Browser encrypts before the relay ever sees plaintext
- One-time claims and short-lived drops
- Open source and self-hostable
Fig. 1 — Diagram
Synthetic workflow illustration — no secret or handoff link is shown
At a glance
- Category
- Developer tool / one-time secret bridge
- Status
- open source
- Source
- public
- Live
- shh.qcfailed.com
- Stack
- Python, JavaScript, PyNaCl, libsodium, Playwright, Docker
- Proof points
- two directions: human → agent and agent → human
- browser-side encryption before upload
- opaque ciphertext relay with one-time claims
- public agent onboarding via /agent.md and /llms.txt
- pytest and real-browser verification
01 / Story
Twenty minutes of cow cuddling
The family had booked a farm tour followed by exactly twenty minutes of cow cuddling. Retrieving the gift-certificate link for that outing exposed the missing half of the product: the agent needed a value from a human, and every available mechanism put that value somewhere it should not go.
The certificate itself never appears here — no value, URL, or vendor detail. What mattered was the pattern: a human-held credential needed to cross into an agent workflow, and the only good answer was a delivery mechanism designed for the boundary, not a redaction feature bolted on afterward.
02 / Story
The original boundary: keep credentials out of chat
The first direction, Human → Agent, exists because credentials should not be pasted into chat or model context. Transcript redaction can scrub a known secret after the fact, but it cannot un-leak a value that was already sent, and it cannot know about values it was never told to look for.
The original flow made the receiving side explicit: the agent creates a receiver keypair and a public delivery link, a person opens the complete link and encrypts in the browser, and the relay stores only opaque ciphertext. The receiver decrypts locally and writes one declared .env value — a fixed target, not an open write primitive.
The receiver private key never enters the delivery link, a request, or normal output. Redaction remains a useful hygiene layer; it is just not the security mechanism.
03 / Story
The reverse direction was the product lesson
The second direction, Agent → Human, came from the same incident viewed from the other side. The agent had a value — the gift-certificate link — that needed to reach a human without passing through chat or model context. Posting plaintext was unacceptable, and a reusable secret would linger.
The reverse flow uses a short-lived one-time reveal instead: the agent reads a value from stdin, encrypts it with a fresh symmetric key, and uploads ciphertext. The agent prints a single-use reveal link whose fragment carries the drop id and the key, the person opens it in the browser, and a one-time claim deletes the ciphertext from the relay.
That is a product need, not a scanner exploit: hand a secret back out of an agent workflow with the same boundary discipline the inbound direction already had.
04 / Flow
Human → Agent
STEP 01
Declared receiver
Agent creates a receiver keypair and a public delivery link; the receiver private key never enters the link.
STEP 02
Browser encrypts
Person opens the complete link and encrypts in the browser — plaintext exists only client-side at this point.
STEP 03
Opaque ciphertext relay
Relay stores only ciphertext plus lifecycle metadata; a reveal URL is a live bearer capability until claimed.
STEP 04
One-time claim
Receiver decrypts locally and writes one declared .env value; the drop is claimed once.
Fails closed
- Plaintext exists only in the person's browser and the receiver's local decrypt step — never in the delivery link, a request, or normal output
- Browser fragments are not sent in ordinary HTTP requests; capability material stays out of server-visible paths where applicable
05 / Flow
Agent → Human
STEP 01
Agent encrypts
Agent reads a value from stdin and encrypts with a fresh symmetric key — no literal secret in argv or chat.
STEP 02
Opaque ciphertext relay
Agent uploads ciphertext; relay stores it once for the drop's short lifetime.
STEP 03
One-time reveal
Person opens the reveal link in the browser and claims it once; claiming deletes the ciphertext from the relay.
STEP 04
Copy / hide
Browser decrypts locally, removes the capability fragment, and shows the value until the user copies or hides it.
Fails closed
- The reveal link is a live bearer capability until claimed — anyone who opens it first can claim the secret
- Fragment removal, the copy/hide lifecycle, and the bounded fallback timer are screen hygiene, not cryptographic containment
06 / Decisions
Selected decisions
Current implementation facts; the source repository is the authority for details:
Capability material stays in URL fragments where applicable
Drop ids and keys live in fragments rather than ordinary request paths, so they are not sent in ordinary HTTP requests.
One-time claim and short TTL
A drop can be claimed once, then the ciphertext is deleted; short time-to-live bounds how long a capability lingers.
Explicit Reveal / Copy / Hide lifecycle
The reveal step removes the capability fragment after decryption, and copy/hide gives the person deliberate control of the plaintext on screen.
Bounded fallback timer as screen hygiene
A 120-second fallback clears the revealed value — privacy hygiene for shared screens, not a containment guarantee.
Payload, storage, and rate boundaries
Limits control abuse and lifecycle; they are not identity or access control.
Strict CSP and no-store where implemented
The served page and relay follow the documented CSP and caching posture; verify the current source for exact headers.
07 / Constraints
What shh is not
Documented boundaries from the security model:
- Not a vault, identity provider, credential broker, or general file-write primitive
- The same-origin operator serves the JavaScript and could replace it to capture future plaintext — not hostile-operator-resistant
- A fully privileged hostile agent is outside the containment boundary
- Reveal links are capabilities, not access control; keep them private and claim promptly
- Short TTLs and one-time claims limit abuse; they are not authentication
08 / Story
Public onboarding for humans and agents
The bare domain is useful once a link exists, but it originally made little sense without a generated link. Public onboarding closes that gap: a landing flow for humans plus machine-readable discovery for agents.
Agents are pointed at https://shh.qcfailed.com/agent.md for the supported handoff helpers, and llms.txt provides a short discovery record. Self-hosted deployments derive the same agent-discovery URL from their active origin.
09 / Story
Dogfooding: the tool carried its own onboarding credential
shh carried the GitHub credential needed to push and open its own public onboarding PR. The credential, capability URL, file contents, and private operational identity are not repeated here — the result is what matters: the tool moved real authentication material across the boundary it was designed for, without putting it in chat or model context.
A delivery-UX lesson came out of the same period: a clickable-link label mattered enough in the Discord channel that the landing copy was refined for how links actually render. Delivery UX is part of a security workflow, not decoration.
10 / Story
How it is verified
The repository runs unit and handoff coverage with synthetic test data, plus real-browser Playwright journeys exercised against an external relay. A Docker container handoff is part of CI, and results were confirmed by reading the CI logs directly rather than trusting a status badge alone.
The curated visual on this page is a synthetic workflow illustration, not a screenshot of a live handoff. No real drop, key, or capability material is shown anywhere in this case file.
One review correction is worth recording: syntax alone did not prove a decoded receiver key had the required 32-byte length. Review added decoded-length validation and a regression test before merge — the lesson is verification discipline, not spectacle.
11 / Story
Honest threat boundaries
The same-origin server supplies the JavaScript; a compromised or malicious operator could replace future client code and capture plaintext before encryption. Self-hosting is the answer when that trust boundary matters.
A fully privileged hostile agent is outside the containment boundary. Reveal links are live capabilities until claimed, and hide/timer behavior protects screen privacy — it is not cryptographic containment. There is no zero-trust, vault, or unhackable claim here.
12 / Evidence
Evidence
The public sources behind this case file:
- shh repository
The README documents the two directions, the security model, self-hosting, and the supported helpers.
- Merged PR #7 — public onboarding and agent discovery
Added the public landing/onboarding and the agent.md discovery path, merged 2026-08-11.
- Merged PR #8 — landing badge refinement
Unified the landing badges, merged 2026-08-11.
Synthetic workflow illustration — no secret or handoff link is shown
A repository-owned synthetic workflow illustration; it is not a live handoff.
13 / Status
Current status and next direction
shh is live at https://shh.qcfailed.com, open source, and self-hostable today. The hosted instance is a best-effort public demo with no account, SLA, or identity guarantee.
Related work: the Request Minimizer case file covers a sibling credential-exposure experiment. No roadmap is invented here; the public agent guide and the repository are the current sources of truth.
Next direction
- Ground any later direction in current repository issues before proposing it; nothing in this case file invents one.