2 March 2026
How to share .env files securely with your team
Every dev team has this problem. A new person joins, or someone sets up a new machine, and someone has to send them the environment variables. Somehow. That "somehow" is usually Slack. Here's why that's a problem and what to do instead.
How teams actually share .env files (and why each method is bad)
There are a handful of patterns that most teams end up using. They're all compromises.
Slack or Teams DM
The most common. Fast, convenient, and the credentials now live in Slack's message history indefinitely. They're searchable, they sync to mobile devices, they're backed up in Slack's infrastructure. A compromised Slack account or a Slack breach means every secret ever DMed is exposed. Slack's own compliance exports make them discoverable by org admins too.
Even worse than Slack. Email is rarely encrypted in transit between servers, it's indexed by every email provider for search, it syncs everywhere, and it tends to stay in inboxes for years. An email containing your production database password from 2021 is probably still sitting in someone's Gmail.
Committed to a private repo
A .env.example with real values, a .env that slipped past
.gitignore, a config file with hardcoded staging credentials.
It happens constantly. Private repos become less private over time as access is shared,
and git history is forever — deleting the file doesn't remove it from history.
Shared Google Doc or Notion page
Better than Slack in that it's at least intentional. But the credentials now live in a document that's accessible to everyone with the link (or everyone in the workspace), is indexed by Google, and accumulates access over time as the team grows. Rotation means updating one doc — which most teams don't do consistently.
A shared password manager entry
Closer to correct — at least the content is encrypted at rest. The weakness is that the password manager holds the key, so the security guarantee is "trust the password manager provider." Shared vault access also tends to accumulate: people who no longer work on the project still have access unless someone actively revokes it.
The core problem: credentials that persist
Every method above has one thing in common: the credentials stick around after they've been received.
The new team member has their local .env set up — great. But the Slack DM still exists.
The email is still in the inbox. The Google Doc is still open.
The correct model is delivery, not storage. The recipient should get the credentials, set them up, and the delivery mechanism should cease to exist. There should be no artifact that an attacker can find months later and use to extract production credentials.
The VoidNote pattern
Create a note containing the .env contents. Share the link. The recipient opens it,
copies the values to their local environment, and the note burns. There is nothing left to steal.
The note is encrypted in your browser with AES-256-GCM before it leaves your machine. The decryption key is in the URL fragment — never transmitted to VoidNote's servers. Even if someone intercepts the link in transit, they can't decrypt the content without the fragment. Even if VoidNote's servers were breached, the attacker gets encrypted bytes they can't read.
# Onboarding a new team member — runs in about 10 seconds
$ cat .env | voidnote create
https://voidnote.net/n/a1b2c3#secretkey
# Send that URL over Slack, email, anything
# They open it once, copy the values, and the note is gone
# The Slack message now contains a dead link — useless
Handling multiple recipients
If three people need the same .env — say, you're setting up a new project and onboarding the whole team at once —
create a multi-view note that allows exactly as many reads as you have recipients:
# 3 team members, 3 views
$ cat .env | voidnote create --views 3
https://voidnote.net/n/a1b2c3#secretkey
# Each person opens the link once
# After the 3rd view, the note is destroyed
# A 4th attempt returns: note not found
You can also send individual notes per person — one URL each — so you know exactly who has retrieved the credentials. If someone loses their note URL before opening it, you create a new one for them without needing to rotate the underlying credentials.
Selective sharing for different environments
Not everyone needs production credentials. A common mistake is sharing the full .env
when a new contractor or junior dev only needs the development or staging values.
VoidNote makes it easy to be selective:
# Staging-only credentials for a contractor
$ voidnote create <<EOF
DATABASE_URL=postgresql://staging-host/app
API_KEY=sk_test_abc123
REDIS_URL=redis://staging-redis:6379
EOF
# Production values never leave your terminal
Credential rotation without the coordination overhead
When you rotate a credential — a compromised API key, an expiring certificate, a database password that's being cycled — you need to get the new value to everyone who uses it. The old pattern is updating the Google Doc and pinging the team on Slack. The new value is now in Slack history too.
The VoidNote pattern: rotate the credential at the source, create a new note with the new value, send the link. Each person who needs it reads once. Done. The note that carried the new value is gone. You've added no new persistent artifact.
# Rotated the Stripe key — share the new one
$ echo "STRIPE_SECRET_KEY=sk_live_newkey..." | voidnote create
https://voidnote.net/n/xyz987#newkey
# Post in #engineering: "Stripe key rotated, link above"
# After everyone reads it: link is dead, Slack has nothing useful
Adding a password for production credentials
For production credentials, add a password. Even if the link ends up somewhere unintended — forwarded to the wrong person, leaked in a support ticket — they can't read the note without the password, which you share through a separate channel:
# Protect production .env with a password
$ cat .env.production | voidnote create --password "$(openssl rand -base64 12)"
https://voidnote.net/n/abc123#secretkey
# Send the URL over Slack
# Send the password over SMS, Signal, or 1Password
# Neither channel alone is useful to an attacker
For teams that want a persistent store
VoidNote isn't a replacement for a full secrets manager like Vault, AWS Secrets Manager, or Doppler if you need a permanent, auditable, access-controlled store for production secrets. Those tools exist for good reasons.
VoidNote solves the specific problem of transferring credentials — the moment when a secret needs to move from one person or system to another. That's where the gap in most teams' security posture is. The secrets manager holds the canonical value. VoidNote is how you get it to the person who needs it without the transfer itself becoming a liability.
Get started
The CLI is the fastest path for teams already living in the terminal. The web UI works for anyone on the team who isn't CLI-first. Either way, the note burns on read and the credentials don't accumulate in chat history.
# macOS / Linux
brew install quantum-encoding/tap/voidnote
# Test it
cat .env | voidnote create
# Or use the web UI — no CLI needed
open https://voidnote.net/new