Why .env files in chat are a liability
Pasting a .env file into chat feels harmless. Where those values end up, why they outlive the conversation, and how to clean up what is already there.
Crunu teamPublished 8 min read
On this page
Almost every team has done it. A new developer needs to run the app locally, the setup guide says "ask someone for the .env", and a teammate pastes forty lines into a direct message. The developer is unblocked in a minute. Nobody thinks about that message again.
This post looks at what actually happens to those forty lines, why the risk is larger than it feels, and what a reasonable replacement looks like. It also covers the part most guides skip: cleaning up the values that are already sitting in your chat history.
A pasted file is not a transfer, it is a copy
When you hand someone a USB stick, you know where the data went. When you paste a file into a chat tool, it lands in several places at once, and each of them has its own lifetime.
- The message history. Chat tools are built to remember. Slack, for example, says that on paid plans data is kept for the lifetime of the workspace by default, unless an admin sets a shorter retention policy (Slack Help Center). A value pasted on someone's first day can still be there when they leave, and long after.
- Search. Anything in history is searchable by everyone who can see the conversation. In a channel, that includes people who join later.
- Devices. The message is delivered to every device where the recipients are signed in: laptops, phones, tablets, each with its own local cache and notifications.
- Integrations. Bots and apps installed in the workspace may have permission to read the channels they are added to.
- Link previews. If the file contains a URL, the chat service may fetch it. Slack's documentation says that when a link is spotted, Slack crawls it to build a preview (Slack docs). A webhook URL or a signed download link with a token in it is a credential in its own right, and now a third-party server has requested it.
None of this is a flaw in any particular chat product. Chat is designed to keep messages, sync them everywhere and make them easy to find. Those are exactly the wrong properties for a production database password.
Why it is worse than it looks
The immediate risk, someone reading the message, is the obvious one. The structural problems are quieter and do more damage over time.
There is no boundary inside the file
A .env file mixes everything a service needs: a log level, a feature flag, a Sentry DSN, a Stripe secret key, a database URL with a password inside it. A developer who needed LOG_LEVEL and a local database received the payment key as well. Teams often paste the production file because it is the one that is "known to work", and the recipient gets production access without anyone deciding to grant it.
There is no revocation
You can delete a message. You cannot delete the copy in someone's notes app, the screenshot they took, or the file they saved to their downloads folder. Once a secret has been shown to a person, the only real revocation is to replace the value at the provider.
There is no record
Six months later, when someone asks "who has the production Stripe key?", the honest answer is "anyone who was in that DM, anyone they forwarded it to, and anyone with access to their laptop". There is no list, because chat was never meant to produce one.
Copies drift
The .env pasted in March is not the one in use in October. One teammate updated a value and pasted the new version in a different thread. Another kept the old file. Bugs that look like configuration mysteries are often two people running different copies of the same file.
Offboarding has no starting point
When someone leaves, removing their chat account takes seconds. Working out which secrets they saw takes days, because the evidence is scattered across conversations. Most teams skip that step, which means old values stay valid indefinitely. The offboarding checklist for engineering teams covers that problem in detail.
What a replacement needs to do
"Use a secrets manager" is the standard advice, but it helps to be specific about which properties actually fix the problems above.
- One source of truth. Each environment's configuration lives in one place, with versions, so there is no question of which copy is current.
- Access per environment. Being able to run the app locally should not imply being able to read production. The boundary should be part of how the data is stored, not a convention.
- Delivery straight to the process. Values should reach the program that needs them without passing through chat, email or a file someone has to remember to delete.
- A safe way to share with people outside the team. Contractors and partners still need the occasional value. They need a channel that expires.
- A record of who received what. So that offboarding and incident response start from facts.
- A clear story for leaks. When a value is exposed, you need to know where it came from and where to reissue it.
The OWASP Secrets Management Cheat Sheet makes a similar case: centralize secrets so that it is clear what each one is for and where to find it.
How Crunu approaches it
Crunu is a team vault for environment variables and secrets, built so that the server stores only ciphertext. Here is how it maps to the list above.
Projects and environments. You create a project, such as web-app, with environments such as development, staging and production. You can drag your existing .env files, or whole folders like ~/.aws, into an environment, and Crunu guesses where each file lives on a computer. Every save creates a version, and the last 100 versions are kept, so you can see what changed and restore an older one. See first project.
A key per environment. Each environment is encrypted with its own key, and that key is sealed separately to each person who has access. A developer who can read web-app / development has no key for web-app / production, so the separation holds even against someone with a copy of the database. The one key per environment post explains why that matters.
Delivery to the process. Instead of keeping a local .env file, a developer signs in with the crunu command line tool and starts the app with the variables of the environment they need:
crunu login --server https://app.crunu.com --email jonas@kiteline.example
crunu unlock --ttl 2h
crunu run --env web-app/development -- npm run devcrunu run starts the program with a clean environment plus the variables of that environment. Nothing is written to disk. See sign in from the terminal. Servers use the same tool as a background service, which is covered in secrets on servers without files on disk.
Share links for outsiders. When someone without an account needs a file, you create a share link. The decryption key is in the part of the URL after #, which the server never sees, and the link only counts as opened when the recipient clicks "Open", so a chat preview does not use it up. Links can expire after a time or a number of views and can require a password. More in sharing a secret with a contractor safely.
A record. The audit log records versions, sign-ins, share links and access changes, and the server keeps track of which person or machine received which version of each environment. When someone leaves, that record turns into an exposure report and a list of values to reissue at providers.
Kiteline, the company in the command example above, is fictional.
Cleaning up what is already in chat
Moving to a vault fixes the future. The secrets already pasted into chat need their own cleanup, and the order matters.
- Find them. Search your chat workspace for strings that tend to appear in secrets:
KEY=,SECRET,TOKEN,PASSWORD,postgres://, and the prefixes your providers use, such assk_live_for Stripe orAKIAfor AWS access key IDs. Check channels for deployment and onboarding first. - Inventory them. For each hit, note the provider, the environment and who could see the message. You do not need the value itself in your notes, only enough to identify it.
- Put the current values in the vault. Load each environment once, from the copy that is actually in use, so the vault becomes the source of truth before you start changing things.
- Reissue what was exposed. Generate new values at the provider for anything that appeared in chat, starting with production, payment and cloud credentials. Store the new value in the vault and roll it out. Then disable the old value at the provider.
- Delete the messages last. Deleting first feels responsible but removes your inventory. Deleting at the end tidies up history; it does not remove copies that already left the chat tool, which is why step 4 comes first.
- Change the habit. Update your onboarding guide so that the instruction is "ask for access to
web-app / development", not "ask someone for the.env".
What a vault does not fix
It is worth being clear about the limits, because they shape the habits you keep.
- People who can read a value can copy it. A vault decides who can decrypt. It cannot control what a person does with plaintext on their own screen. Crunu hides values in the interface by default, but that protects against accidents such as screen sharing, not against someone who wants a copy.
- Old values stay valid until you reissue them. Rotating encryption keys in a vault protects future versions. It does nothing to a Stripe key someone already saw. Crunu does not reissue values at providers for you; it tells you which ones to reissue.
- Crunu does not scan chat or code. It will not find secrets that are already scattered around. The search in the cleanup steps above is something you run yourself.
The goal is not that secrets never touch a human. It is that every time one does, it happens deliberately, to the right person, with a record, and with a clear path to replace it later. Chat cannot give you any of those. A vault built for the job can.
If you want to compare approaches before choosing, see Crunu vs .env files in chat or the vault feature overview.
Sources
- Customize data retention in Slack, Slack Help Center, checked October 27, 2026.
- Unfurling links in messages, Slack developer docs, checked October 27, 2026.
- OWASP Secrets Management Cheat Sheet, checked October 27, 2026.