Your .env is a liability

Plaintext secrets. Scattered across laptops. Pasted in Slack. Committed to git that one time. You know the drill.

Fix it in 60 seconds.

the fix
envv push .env --env dev
Encrypted. Now it's ciphertext.
rm .env
Plaintext gone. Good.
envv run -- npm start
Server running on :3000
Secrets in memory. Zero on disk.

The Uncomfortable Truth

You already know this. You've just been too busy to fix it.

It's in Slack

Someone asked for the Stripe key. You sent it. It's still there, searchable, forever. Anyone who joins the channel can find it.

It's in Git

Not now—you're careful now. But six months ago? That .env.example that wasn't actually an example? It's in the history.

Everyone Has Everything

The intern has the production database URL. The designer has the payment keys. Not because they need them. Because that's how .env files work.

What if secrets just worked?

Encrypted by default. Scoped by role. Audit trail included.

Your Code Doesn't Change

Same process.env. Same patterns. Different security posture.

server.js — exactly what you'd write anyway

const express = require('express');
const app = express();

// These come from envv, decrypted in memory
const STRIPE_KEY = process.env.STRIPE_API_KEY;
const ANALYTICS_ID = process.env.ANALYTICS_KEY_GOOGLE;

// Your code doesn't know or care where they came from
app.get('/api/config', (req, res) => {
  res.json({
    analytics: ANALYTICS_ID ? 'enabled' : 'disabled',
    payments: STRIPE_KEY ? 'ready' : 'not configured'
  });
});

app.listen(3000);

package.json — before

{
  "scripts": {
    "start": "node server.js"
  }
}
// Assumes .env exists
// Assumes it has the right values
// Assumes nobody committed it

package.json — after

{
  "scripts": {
    "start": "envv run -- node server.js"
  }
}
// Decrypts at runtime
// Injects into process
// Never touches disk

Not Everyone Needs Everything

This is the part that changes how you think about secrets.

Marcus — Engineer

Needs to debug payment flows. Deploy to production. Fix that thing at 2am.

  • ✓ Analytics keys
  • ✓ Stripe credentials
  • ✓ Database access

Ada — Designer

Runs the app locally to test UI changes. Looks at analytics to understand users.

  • ✓ Analytics keys
  • ✗ Stripe credentials
  • ✗ Database access

Jordan — Content

Checks campaign metrics. Never touches code. Doesn't need to.

  • ✓ Analytics keys
  • ✗ Stripe credentials
  • ✗ Database access
when Ada runs the app
envv run -- npm start
Loaded 2 secrets for role: designer
ANALYTICS_KEY_GOOGLE ✓
ANALYTICS_KEY_MIXPANEL ✓
Server running on :3000
App works. Payment code gracefully disabled.

Patterns That Bite

The silent default

const key = process.env.API_KEY || 'dev-key';

// Runs fine with the default
// Ships to production with the default
// You find out when Stripe emails you

The loud failure

const key = process.env.API_KEY;
if (!key) throw new Error('API_KEY required');

// Fails immediately
// Fails obviously
// Fails before production

The logging accident

console.log('Config:', process.env);

// Great for debugging
// Also great for exposing every secret
// To every log aggregator
// Forever

The intentional log

console.log('Config:', {
  nodeEnv: process.env.NODE_ENV,
  port: process.env.PORT
});

// Log what you mean to log
// Nothing more

Monday Morning

New hire starts. How long until they're productive?

Before envv

9:00  "Who has the .env file?"
9:15  Waiting for Sarah to get to her laptop
10:30 Sarah sends partial .env via Slack
10:45 "Missing DATABASE_URL"
11:00 Sarah on a call
12:00 Lunch
13:00 Finally has all secrets
13:15 App runs

Total: half a day

With envv

9:00  envv auth register
9:01  envv pull --env development
9:02  envv run -- npm start
9:03  App runs

Total: 3 minutes

(Sarah never interrupted)

The Alternative

What happens if you don't fix this?

Best case

Nothing. You get lucky. The .env file never leaks, nobody leaves on bad terms, git history stays buried.

Medium case

Someone leaves. You spend a weekend rotating every secret because you don't know what they had access to.

Worst case

Your Stripe keys are on GitHub. Hackers find them in minutes. You explain to customers why their cards were charged.

60 Seconds to Fix It

do it now
# Install
curl -fsSL https://getenvv.com/envv | sh
# Encrypt your existing .env
envv push .env --env dev
# Verify it works
envv run -- node -e "console.log(process.env.API_KEY)"
# Delete the liability
rm .env && echo ".env" >> .gitignore
# Commit the encrypted version
git add .env.encrypted .gitignore && git commit -m "encrypt secrets"
Done. Secrets encrypted. Plaintext gone.

You know this needs to happen.

curl -fsSL https://getenvv.com/envv | sh

Windows? irm https://getenvv.com/install.ps1 | iex