It happened on a Tuesday.
A new hire, trying to get their local environment working, accidentally committed our production API keys to a public GitHub repository. What followed was a blur of adrenaline and panic: we had to completely take down the repo, invalidate dozens of keys, and manually rotate our entire infrastructure one service at a time. It was a hectic, miserable afternoon.
But when the dust settled, we realized something important: we couldn't blame the engineer. The real culprit was the .env file itself. We had built a system where security relied entirely on humans remembering to update a .gitignore file. That was the day we declared war on .env files.
The Hidden Cost of "DM me the secrets"
We built something to solve exactly this. But first, let me show you how we got there.
The GitHub leak was our explosive trigger, but as we audited our workflow, we realized .env files were causing a slow, painful bleed across our entire company.
Whenever non-developers—like product designers, PMs, or QA engineers—wanted to preview a project locally, they couldn't just clone and run it. They had to ping an engineer: "Hey, can you send me the latest .env?"
This created a massive bottleneck. Non-developers would sometimes wait hours for an engineer to finish a deep-focus task just to get a text file. Worse, those secrets were being copy-pasted into Slack DMs, where they lived forever. We were trading our company's security for temporary convenience.
Design Exploration: The UX vs. Security Trap
We started looking at existing secret managers. The market is full of enterprise-grade tools, but we quickly found a glaring issue: they were built for machines, not for humans.
Most solutions required complex CLI authentications, deep AWS knowledge, or cumbersome UI dashboards. If we forced our designers to use them just to run a local localhost:3000 preview, we would completely destroy their productivity.
Our design and engineering teams sat down and established two non-negotiable constraints:
- Zero-friction UX: It had to be so simple that a non-developer could run it on their first try without reading a manual.
- Absolute Top-Tier Security: It needed to be vastly more secure than anything else on the market, meaning true End-to-End Encryption (E2EE) and zero local traces.
This is a classic software engineering tradeoff: usually, as security increases, usability plummets. We needed to break that rule.
The Engineering Challenge: Killing the Disk
If we wanted to eliminate the risk of .env files being accidentally committed, we had to stop writing them to the disk entirely.
We experimented with several approaches, but ultimately realized the safest way to manage local secrets is to inject them directly into the runtime process.
Instead of a developer running npm run dev and having the framework look for a .env file, we wanted them to run our tool, which would securely fetch the secrets, hold them in memory, and execute npm run dev with the environment variables pre-loaded.
But memory injection alone wasn't enough. What if a developer left a session running? We debated the architecture and eventually engineered a system of Just-In-Time (JIT) leases. When a developer or designer boots up a project, they are granted a temporary, encrypted lease for those secrets. When the session ends, the access evaporates.
# Before RunEnv
npm run dev # prays .env file exists and isn't outdated
# With RunEnv
runenv run -- npm run dev # secrets injected. zero disk. done.
The Breakthrough: Invisible Security
The real breakthrough came when we realized we could bridge the gap between our CLI and the tools our team already used.
We built a VS Code extension and a lightweight CLI. Because our architecture handled the heavy lifting of the E2EE engine in the background, the surface area for the user was practically invisible.
For the engineering team, it meant typing a single command to sync and run their environment. For the design team, it meant clicking a button in VS Code to spin up a perfectly configured local preview. No Slack DMs. No copy-pasting.
The Final Implementation and Results
Today, our workflow looks completely different. We replaced plain-text .env files with dynamic, encrypted runtime injection.
The results were immediate and highly measurable:
- Instant setups: Project onboarding for both engineers and non-engineers dropped from hours to seconds. No one waits on anyone else to start working.
-
Zero leaks: Because secrets are never written to a
.envfile on disk, they cannot be accidentally committed to GitHub. - A clean Slack: We have entirely eliminated the exchange of production or staging keys via direct messages.
Lessons Learned
If there is one thing we took away from this journey, it’s that developer experience is a security feature. If your security protocols are too hard to use, your team will find workarounds. They will DM keys on Slack, they will email text files, and eventually, someone will push a key to a public repo. By focusing on frictionless access for non-technical users, we accidentally built the most secure architecture our team has ever had.
If your team is still slacking .env files to each other, or if you’ve ever had the heart-dropping experience of a leaked GitHub key, you don't have to build this from scratch. We spun our internal solution out into RunEnv a frictionless, end-to-end encrypted secret manager built for humans. Try RunEnv with your team today and kill your .env files for good.
Top comments (0)