DevForge

How to stop .env files from leaking into git history

A committed .env is one of the fastest ways to expose secrets to everyone with repo access — and git keeps them forever. This guide covers diffing, rotating, and auditing environment variables so you can stop the leak and keep the surface small.

Last updated: June 2026 · ~6 min read

Why .env leaks keep happening

Most teams know the rule: do not commit .env. Yet it happens constantly. A new dev runs the wrong command, a linter rule is misconfigured, or someone copies a file into a build artifact that gets checked in. The problem is rarely intent — it is friction. The fixes below are designed to be easy enough that people actually do them.

The failure modes look familiar:

Step 0 — Install Envault

Envault is published to the project's own package index (it is not on public PyPI yet), so point pip at the index — or install straight from source:

# From the project package index (recommended)
pip install --index-url https://coding-dev-tools.github.io/pypi-index/simple/ rh-envault

# Or directly from source (always tracks the latest code)
pip install git+https://github.com/Coding-Dev-Tools/envault.git

Requires Python 3.10+ — pure Python, no compiled wheels. The installed CLI entry point is rh-envault.

Step 1 — Diff before merge

The fastest way to catch a leak is to compare environments in CI before the code ships. Envault diffs two environments and highlights missing, added, or changed values — secrets are masked in the output.

# Compare dev vs prod
rh-envault diff dev prod

# Fail the CI build if prod has keys staging does not
rh-envault diff staging prod --fail-on-missing

# Compare two .env files directly
rh-envault diff-files .env.dev .env.prod

Put the diff in a pre-merge hook or your CI pipeline. A red build is cheaper than rotating secrets after a release.

Step 2 — Rotate as part of deploy

If a secret has leaked, rotation is the fix — not deletion. Envault infers the secret type and generates a value that fits the slot:

# Rotate a single secret
rh-envault rotate DB_PASSWORD

# Rotate with a dry run so you can preview the value
rh-envault rotate API_KEY --dry-run --show

# Rotate everything in an environment
rh-envault rotate-all --env prod

Rotate in the branch, land it, then sync to prod in the same deploy. That keeps the new value in one place instead of scattered across environments.

Honest note on tiers. The free CLI covers diff, sync, and rotate for individuals and open-source use, rate-limited. Smart secret type inference, bulk rotate-all, unlimited audit history, team shared configs, dashboard, compliance reports, and secret-store integrations are part of the Individual plan ($12/mo). We would rather flag that up front than have a command fail mid-tutorial.

Step 3 — Keep plaintext surface small

The config file is Git-friendly. The secrets are not. Envault stores configuration in a .envault.yml file you can commit, while secrets live outside version control. Every rotate, sync, and diff is logged to .envault-audit.log so you have a timestamped record instead of relying on memory.

# Inspect recent rotations
rh-envault audit --limit 20

# Filter by key
rh-envault audit --key DB_PASSWORD

# Filter by action
rh-envault audit --action rotate

When something goes sideways, you have a log to read instead of a Slack thread from six months ago.

Step 4 — CI runner as pass-through, not a vault

The pattern that keeps recreating leaks is echo > .env inside a job. Instead, let Envault serve the secrets over HTTP locally and have the runner fetch them at runtime:

# Start the secrets API on localhost
rh-envault serve --api-key $ENVAULT_API_KEY

# Fetch a single secret in a job
curl -H "Authorization: Bearer $ENVAULT_API_KEY" \
  http://localhost:8080/secrets/DB_PASSWORD

For MCP server sidecars and AI agent runtimes, Envault exposes a GET /secrets and GET /secrets/{key} endpoint with Bearer token auth. No plaintext secrets are written into the workflow file or uploaded as artifacts.

What you actually get

CapabilityFreeIndividual ($12/mo)
Diff environments
Sync with conflict resolution
Rotate / rotate-all
Audit trail7 daysUnlimited
Smart secret type inference
Bulk rotate-all with dry-run
Secret store integrations
Secrets HTTP API (serve)
Team shared configs
Dashboard & compliance reports

Source: the Envault README pricing & per-tier feature table. A Suite plan ($49/mo) covers all 11 Revenue Holdings CLI tools; Team ($79/mo) adds a shared config store. Annual billing saves 20%.

Stop copy-pasting secrets between files.

Envault is MIT-licensed and works fully offline on the free tier — no telemetry, no phone-home.

Get Envault on GitHub Also: Rotate API keys in CI →

FAQ

What should I do if .env is already in my git history?

Rotate every secret that was present in the committed file immediately. Use rh-envault rotate to issue fresh values, then sync the new values to the environments that consumed them. A .env leak in history is only dangerous if the values are still valid — Envault does not rewrite commits, but rotation makes the old values useless.

Does Envault rewrite my git history?

No. Envault works with your current .env files and secret stores. It does not run git-filter-repo or rewrite commits. The focus is on stopping new leaks and rotating exposed values so the old ones stop mattering.

Can Envault integrate with AWS SSM, Vault, or Doppler?

Yes. rh-envault store get/set/list reads and writes secrets from AWS SSM, HashiCorp Vault, Doppler, and 1Password. These integrations require the Individual plan or higher. If you only need local diff / sync / rotate on the free tier, no external store is required.

Is there a way to test this without touching production secrets?

Yes. Every command supports a --dry-run flag. Diff only reports changes; rotate with --dry-run --show prints the generated value without writing it. The free tier has no eval period because it is already free — install it, point it at a throwaway .env, and see if the workflow fits.

Envault is part of Revenue Holdings — a suite of developer CLI tools. See also How to rotate API keys safely in CI/CD for API-key-specific rotation guidance.