env-auditor
Audit environment variable consistency across your codebase. Finds vars used in code but missing from .env.example, stale vars nobody references anymore, and required vars with no default value; in any language.
$ env-auditor .
env-auditor — environment variable audit
──────────────────────────────────────────
✗ 3 undocumented variables (in code, missing from .env.example)
DATABASE_URL src/db/connection.py:14
STRIPE_WEBHOOK_SECRET src/payments/webhook.py:8, src/payments/webhook.py:31
REDIS_URL src/cache.py:22
⚠ 2 stale variables (in .env.example, not found in code)
OLD_PAYMENT_KEY
DEPRECATED_FEATURE_FLAG
○ 2 variables with no default value (empty in .env.example)
SECRET_KEY
JWT_SECRET
⚡ 1 dynamic reference (runtime key construction — cannot audit statically)
src/config/loader.py:45 → process.env[configKey]
──────────────────────────────────────────
Result: FAIL (exit code 1)
Why
Your .env.example is a contract. It tells new contributors what the app needs to run. Over time that contract drifts: someone adds process.env.NEW_KEY to the source and forgets to document it, or removes a feature but leaves the stale key rotting in .env.example. env-auditor catches both automatically, in CI, before it becomes someone else's debugging session.
Installation
pip install env-auditor
Requires Python 3.10+. Zero runtime dependencies — pure stdlib.
Usage
# Audit current directory against .env.example (default)
env-auditor
# Audit a specific project
env-auditor /path/to/project
# Use a different env file
env-auditor --env .env.production
# Multiple env files (keys merged — union)
env-auditor --env .env.example --env .env.staging
# Strict mode: fail on stale vars too
env-auditor --strict
# JSON output for tooling / dashboards
env-auditor --format json | jq .undocumented
# Suppress specific sections
env-auditor --ignore-stale --ignore-missing
# Exclude extra directories
env-auditor --exclude vendor --exclude third_party
Config file
Commit a .env-auditorrc at your project root to persist settings for your whole team:
# .env-auditorrc
env_files = [".env.example", ".env.staging"]
exclude_dirs = ["vendor", "third_party"]
ignore_stale = false
strict = true
ignore_keys = ["CI", "HOME", "USER"]
required_keys = ["DATABASE_URL", "SECRET_KEY"]
Or add it to pyproject.toml under [tool.env-auditor]:
[tool.env-auditor]
env_files = [".env.example"]
strict = true
ignore_keys = ["CI"]
CLI flags always override config file values.
ignore_keys excludes specific variable names from every category (undocumented, stale, missing values, required). required_keys is the inverse: names that must appear in at least one env file; always reported as a failure if absent, whether or not they're referenced in code (useful for infra-only vars like DATABASE_URL that no source file ever touches directly).
Supported languages
| Language | Detected patterns |
|---|---|
| JavaScript / TypeScript | process.env.VAR, process.env['VAR'], process.env["VAR"] |
| Python | os.environ['VAR'], os.environ.get('VAR'), os.getenv('VAR') |
| Go | os.Getenv("VAR"), os.LookupEnv("VAR") |
| Shell | $VAR, ${VAR} (.sh, .bash, .zsh only) |
| Docker | ENV VAR, ARG VAR in Dockerfiles |
| Ruby | ENV['VAR'], ENV["VAR"], ENV.fetch('VAR') |
Dynamic references like process.env[someVariable] are flagged separately, they can't be statically audited.
CLI reference
| Flag | Description | Default |
|---|---|---|
PATH |
Root directory to scan | . |
--env FILE |
Env file(s) as source of truth. Repeatable. | .env.example |
--config FILE |
Path to config file | auto-discover .env-auditorrc |
--ignore-stale |
Suppress stale variable report | off |
--ignore-missing |
Suppress empty-value report | off |
--format [text|json] |
Output format | text |
--no-color |
Disable ANSI colors | off |
--exclude DIR |
Extra directories to skip. Repeatable. | — |
--strict |
Exit 1 on stale vars too | off |
--version |
Show version and exit | — |
Exit codes
| Code | Meaning |
|---|---|
0 |
Clean |
1 |
Undocumented vars found, stale vars with --strict, or missing required_keys |
2 |
Tool error — bad args, missing files, etc. |
CI integration
Block deploys when env vars drift:
# .github/workflows/deploy.yml
jobs:
env-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- run: pip install env-auditor
- run: env-auditor --strict
Save the report as a CI artifact:
- run: env-auditor --format json > env-auditor-report.json || true
- uses: actions/upload-artifact@v4
with:
name: env-auditor-report
path: env-auditor-report.json
For monorepos, run per-service:
- run: env-auditor services/api --env services/api/.env.example
- run: env-auditor services/worker --env services/worker/.env.example
Security
- Symlinks are never followed
- Files over 1 MB are skipped (with a warning)
- Lines over 2000 characters are skipped (ReDoS protection)
--excludepaths are validated to be within the scan root; path traversal rejected- Actual
.envvalues are never stored, logged, or printed; only key names - No network calls, no telemetry, entirely local
Development
git clone https://github.com/SemTiOne/env-auditor
cd env-auditor
pip install -e .
pip install pytest pytest-cov
pytest --cov=env_auditor --cov-report=term-missing
License
MIT
Metadata
Release files for env-auditor 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| env_auditor-0.2.1.tar.gz | 33.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| env_auditor-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 59.4 kB
Release files / env_auditor-0.2.1.tar.gz
| Download URL | env_auditor-0.2.1.tar.gz |
|---|---|
| Size | 33.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
92c2aaa5af1c1fa6b2a7ca4e8a3c02d0f18896398459434cf93e95458c4a22f8
|
|
BLAKE2b-256 checksum How to use checksums |
9aa81467125ccbf0cef3a56d48ee03a64e8977b486d69c008115fbebca1d2bc8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.
Transparency logRelease files / env_auditor-0.2.1-py3-none-any.whl
| Download URL | env_auditor-0.2.1-py3-none-any.whl |
|---|---|
| Size | 26.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1fef3d4fc42619da9c5929fa6029990808e2e4098e0e0cc44f827599b3b87e94
|
|
BLAKE2b-256 checksum How to use checksums |
c069df11de6d0ce6234067a0856a4e3f45f09838bd56f5ededcefc7eb82009b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.
Transparency log