envaudit
A fast, zero-dependency Rust CLI for detecting .env drift, validating environment files against .env.example, and scanning for accidentally committed secrets.
Installation
From crates.io
Install the latest release using Cargo. Requires Rust 1.70 or newer.
cargo install envauditBuilding from source
Clone the repository and build with Cargo. Useful for contributing or running unreleased changes.
git clone https://github.com/phonotechnologies/envauditcd envauditcargo build --release./target/release/envaudit --versionThe compiled binary is at target/release/envaudit. Add it to your PATH.
Command Reference
envaudit exposes three subcommands. Each command exits with a non-zero code when issues are found, making it suitable as a CI gate.
envaudit --helpenvaudit scan
Compares all discovered .env files in the current directory tree and reports keys that are present in some files but missing from others. Useful for catching configuration drift between environments.
envaudit scan [OPTIONS] [PATH]envaudit scanenvaudit check
Validates a .env file against a .env.example template. Reports keys that are required (present in .env.example) but missing from .env, and keys in .env that are not documented in .env.example.
envaudit check [OPTIONS]envaudit check --env .env.production --example .env.exampleenvaudit secrets
Scans .env files for patterns that look like real secrets. Intended to catch cases where developers have committed actual credentials instead of placeholder values. Useful as a pre-commit hook or CI gate.
envaudit secrets [OPTIONS] [PATH]envaudit secrets --include-exampleJSON Output
All three commands support --format json. This is the recommended format for CI pipelines, scripts, and integrations. The structure is consistent across commands.
scan --format json
{
"command": "scan",
"ok": false,
"issues": [
{
"type": "missing",
"key": "DATABASE_POOL_SIZE",
"present_in": [".env.local", ".env.staging"],
"missing_from": [".env.production"]
},
{
"type": "extra",
"key": "LEGACY_API_ENDPOINT",
"present_in": [".env.staging"],
"missing_from": [".env.local", ".env.production"]
}
],
"files_scanned": [".env.local", ".env.staging", ".env.production"],
"issue_count": 2
}check --format json
{
"command": "check",
"ok": false,
"env_file": ".env",
"example_file": ".env.example",
"missing": [
{ "key": "STRIPE_SECRET_KEY", "required": true },
{ "key": "SENDGRID_API_KEY", "required": true }
],
"undocumented": [
{ "key": "MY_LOCAL_DEBUG", "value_preview": "true" }
],
"issue_count": 3
}secrets --format json
{
"command": "secrets",
"ok": false,
"detections": [
{
"file": ".env.example",
"line": 14,
"key": "STRIPE_KEY",
"pattern": "stripe-secret-key",
"value_preview": "sk_live_a1b2..."
},
{
"file": ".env.example",
"line": 22,
"key": "AWS_SECRET",
"pattern": "aws-access-key",
"value_preview": "AKIA..."
}
],
"files_scanned": [".env.example"],
"detection_count": 2
}CI tip: Use --format json | jq to filter and post-process results. Combine with the exit code to fail the build cleanly.
Exit Codes
envaudit uses standard POSIX exit codes. This makes it straightforward to use as a gate in CI pipelines, pre-commit hooks, and shell scripts.
| Code | Meaning |
|---|---|
0 | No issues found. All checks passed. |
1 | Issues detected (drift, missing keys, or secrets found). |
2 | Invalid arguments or missing required flags. |
3 | File not found or could not be read. |
- name: Check .env drift
run: envaudit scan --quiet
# Fails the step if exit code != 0
- name: Validate .env against template
run: |
envaudit check --format json > env-report.json
cat env-report.json | jq '.ok'