Show HN: Stasher – Burn-after-read secrets from the CLI, no server, no trust
I built it because I just wanted to share a password. Not spin up infra. Not register for some "secure" web app. Not trust Slack threads. Just send a secret.
Secrets are encrypted client-side with AES-256-GCM. You get a `uuid:key` token to share. Once someone reads it, it's gone. If they don't read it in 10 minutes, it expires and deleted.
Everything is verifiable. Every release is signed, SLSA-attested, SBOM-included, and logged in the Rekor transparency log. Every line of code is public.
There's also a browser-based companion: https://app.stasher.dev — works in a sandboxed popup using the same encrypted model. Share from the terminal, pick up in the browser.
No data stored unencrypted. No metadata. No logs. No surveillance.
---
GitHub (CLI): https://github.com/stasher-dev/stasher-cli GitHub (App): https://github.com/stasher-dev/stasher-app API (Cloudflare Worker): https://github.com/stasher-dev/stasher-api CI/CD (Open): https://github.com/stasher-dev/stasher-ci NPM: https://www.npmjs.com/package/stasher-cli Website: https://stasher.dev Browser App: https://app.stasher.dev (runs in sandbox from https://dev.stasher)
Built with Cloudflare Workers, KV, and Durable Objects. All code open, auditable, and signed.
Try it:
```bash npx enstash "vault code is 1234#" npx destash "uuid:base64key"
thanks for reading
And your flow is: I encrypt my password; I upload the encrypted password to your server.
And I share the password to the encrypted password as plain text.
Why do I have to upload the encrypted password to your server, and not just use signal disapearing messages, or telegram secure channel disappearing messages to share the encrypted password there.
And I can use any other side channel to share the second password, like whatsapp, or regular plain mail.
It feels to me that you made a two step process into a one step process but increased the risk by adding you in the middle.
Why would I offload my trust to you instead of doing the second step?
I built Stasher for me. I wanted an easy, CLI-first way to share one-time secrets without worrying about accounts, apps, or trust. If Signal or GPG works better for you that’s totally cool.
Stasher exists to make casual, secure sharing simpler not to replace tools you already trust.
It's just that the entry level for adopting a new tool (for other people) is:
Convince my recipient to use this system instead of "Why not just send the password as we usually do on our secret chat."
And then we spend 20 minutes talking about it and me advocating for their unknown and unaccountable creator.
https://github.com/pglombardo/PasswordPusher
East to deploy, and just works, nice set of sane features and defaults.
1. Code is largely if not entirely written by AI
2. Author is completely anonymous, using a dedicated GitHub and HN account for this specific project
Both of these are really bad for security-sensitive software.
I hadn’t considered your second point, but even the authors GH account has an AI picture. I have no idea who this person is or what online/HN reputation they have.
I’m not anonymous, just cautious. I’m a solo builder, and this is a focused identity for the project. In fact, that's why I implemented full supply chain transparency from day one: signed releases, SLSA attestations, SBOMs, and Rekor logs. You don't need to trust me you can see the code for your self.
Ultimately, you're right — if you can't verify it, you shouldn't trust it.
That’s the whole point of the system: zero trust and verifiable cryptographic guarantees.
Appreciate the scrutiny
More importantly, this project is not "zero trust" and calling it such is borderline deceptive.
I can verify the artifacts you're shipping contain the code in the repo (or I could just clone the repo myself), but I cannot automatically verify that your code is non-malicious and free of bugs. That is what I am trusting when using your software, and I have serious doubts about the "free of bugs" part for AI generated software.
But maybe that’s just me.
The repo is public. The releases are signed. The attestations are published. Nothing hidden.
If that’s not enough — totally fair and I am sure many others would agree. Appreciate your point of view and taking time to give feedback.
That means:You can verify every artifact against its source code i.e I have not tampered with the code post deployment. for example part of the build is a dry-run on the worker build, this is stored as part of the build so you can see / confirm the exact code that was uploaded and this code is signed.
If I were to release something like this then people can see that 1) this is a guy with >20 years of various contributions to open source and he seems like a basically competent guy we can trust (as much as you can ever trust a single person), but also that 2) he's not a crypto guy and there may very well be oversights. Maybe there are none, but you know...
If someone like, say, Filippo Valsorda would release someone like this, then people could see that 1) is basically the same as me, and 2) he's also a well known crypto guy with a good track record. This is not a guarantee there are no oversights, but I would certainly be surprised if there were major ones. I would certainly trust that more than anything I would write.
The whole signing stuff is kind of a red herring IMO. I mean, it's not bad to have I guess, but honestly I don't really care. If anything, focusing to strongly on "box ticking security" so early on seems like the wrong thing to focus on.
CLI uses node.js built-in crypto module only -randomBytes - createDecipheriv - createCipheriv.
Web app uses Web Crypto API only.
I'll send Filippo a Postcard and see if he will review it :-P
npx enstash "my secret"
Stasher performs everything locally:
Generates a random 256-bit encryption key
Encrypts your secret using AES-256-GCM
Sends only:
the ciphertext
the IV (initialization vector)
the auth tag
a randomly generated UUID
The encryption key is never sent to the server. It never leaves your machine.
You are then shown a single string:
uuid:base64key
The uuid points to the encrypted stash on the server
The base64key is the encryption key you just generated
Only the person who has both parts can decrypt the secret
How You Share the Secret
You send the full uuid:base64key token to your recipient — over any channel you like slack or whatever.
When they run:
npx destash "uuid:base64key" on the token
Stasher:
Fetches the encrypted stash using the uuid
Deletes it immediately (burn-after-read)
Decrypts it locally using the base64key
Shows the secret
The server never sees the key. Not during upload or during retrieval.
>The uuid points to the encrypted stash on the server
No servers… “on the server.” hmmm, I must be missing something.
Stasher enforces expiry in two layers:
Reactive expiry — When someone tries to retrieve a stash (destash), the Durable Object checks the creation timestamp before serving. If it's older than 10 minutes, it refuses the request.
Proactive cleanup — Every stash’s Durable Object sets a scheduled alarm to self-destruct after 10 minutes. This removes the coordinating DO and ensures the encrypted blob in KV expires (via TTL).
So even if someone tries to cheat the system, or access after the 10-minute window, they’ll get an error — the stash is gone.
This is part of what makes it “burn-after-read, or expire-after-time”. No guessing, no timers in memory or cron job workers.
How are salts handled?
Stasher uses AES-256-GCM, which does not require a traditional salt like in password hashing (e.g. PBKDF2, bcrypt). Instead, it uses an IV (initialization vector).
With a fresh 96-bit IV is generated for every encryption
AES-GCM uses that IV as part of the encryption process, ensuring non-deterministic ciphertext. The IV is not secret, and is uploaded alongside the ciphertext and GCM tag
On decryption, the IV is used to reconstruct the exact same cipher context
So in short: No static salts and no reused IVs
Everything you need to decrypt is bundled with the encrypted stash, except the key, which stays with the user (as part of the uuid:base64key token)
> Share secrets from your terminal. One-time only. No accounts. No backend. No BS.
A server sure sounds like a backend to me.
>Buzzwords
>Author's English (when not written by a LLM) sounds translated
Doesn't inspire confidence.
Use GPG, it's not difficult. For non-technical folks, use signal or disappearing messages. For slightly more secure comms with non-technical people, use a combination of rot13 / caesar / similar.
Heh, maybe not for you and me, but if you've never tried to coach a less-technical person through setting up GPG and then using to encrypt/decrypt, it's an eye-opening experience
you probably want to unset HISTFILE and then set +o history before sending these commands to bash