Environment Validator
Validate environment configuration for completeness and security. Output to `.claude/audits/ENV_REPORT.md`.
Overview
Environment Validator
Validate environment configuration for completeness and security. Output to .claude/audits/ENV_REPORT.md.
Check
Completeness
- All vars in .env.example exist in .env
- No undocumented vars in .env
- Required vars have values (not empty)
- URL vars are valid format
Security
- No secrets in version control
- No secrets in client-side code
- API keys not exposed in logs
- Sensitive vars properly named (contain SECRET, KEY, PASSWORD)
Environment Consistency
- Dev vs prod config differences documented
- No localhost URLs in production config
- No debug flags in production
- Proper SSL/TLS settings per environment
Format & Values
- Boolean vars are true/false (not 1/0 or yes/no)
- URL vars include protocol
- Port vars are valid numbers
- No trailing whitespace
Commands
# Compare .env.example vs .env
comm -23 <(grep -oE "^[A-Z_]+=" .env.example | sort) <(grep -oE "^[A-Z_]+=" .env | sort) 2>/dev/null
# Find undocumented vars
comm -13 <(grep -oE "^[A-Z_]+=" .env.example | sort) <(grep -oE "^[A-Z_]+=" .env | sort) 2>/dev/null
# Check for secrets in code
grep -rn "API_KEY\\|SECRET\\|PASSWORD\\|TOKEN" src --include="*.ts" --include="*.tsx" | grep -v "process.env"
# Find empty vars
grep -E "^[A-Z_]+=\\s*$" .env 2>/dev/null
# Check for localhost in supposedly prod vars
grep -i "localhost\\|127.0.0.1" .env 2>/dev/null
# Find hardcoded secrets
grep -rn "sk_live\\|pk_live\\|ghp_\\|gho_\\|Bearer " src --include="*.ts"
Output
# Environment Report
## Status: [VALID / INVALID]
| Check | Status | Details |
|-------|--------|---------|
| Completeness | PASS/FAIL | X missing vars |
| Security | PASS/FAIL | X exposed secrets |
| Format | PASS/WARN | X format issues |
## Missing Variables
Variables in `.env.example` but not in `.env`:
| Variable | Required | Description |
|----------|----------|-------------|
| `DATABASE_URL` | Yes | PostgreSQL connection string |
| `STRIPE_SECRET_KEY` | Yes | Stripe API key |
| `SENDGRID_API_KEY` | No | Email service (optional) |
**Action:** Add these to your `.env` file
## Security Issues
### ENV-001: Secret Exposed in Code
**Severity:** Critical
**File:** `src/lib/stripe.ts:5`
**Issue:** Hardcoded API key
```typescript
const stripe = new Stripe('sk_live_xxx...'); // EXPOSED
Fix: Use process.env.STRIPE_SECRET_KEY
ENV-002: Secret in Client Bundle
Severity: Critical
File: src/app/page.tsx:12
Issue: Server secret accessible to client
const apiKey = process.env.API_SECRET; // Not NEXT_PUBLIC_ but still exposed
Fix: Only access secrets in server components/API routes
ENV-003: .env Committed to Git
Severity: High
File: .env
Issue: Found .env in git history
Fix:
- Add
.envto.gitignore - Rotate all exposed secrets
- Use
git filter-branchto remove from history
Format Issues
ENV-004: Empty Required Variable
Variable: SMTP_PASSWORD=
Issue: Variable defined but empty
Fix: Set a value or remove if optional
ENV-005: Invalid URL Format
Variable: API_URL=api.example.com
Issue: Missing protocol
Fix: API_URL=https://api.example.com
ENV-006: Development Value in Production
Variable: DEBUG=true
Issue: Debug mode should be off in production
Fix: Set DEBUG=false for production
Undocumented Variables
Variables in .env but not in .env.example:
| Variable | Value (redacted) | Action |
|---|---|---|
LEGACY_API_KEY | xxx... | Add to .env.example or remove |
TEST_MODE | true | Document purpose |
Environment Template
Required .env.example format:
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
# Authentication
NEXTAUTH_SECRET=generate-with-openssl-rand-base64-32
NEXTAUTH_URL=http://localhost:3000
# External Services
STRIPE_SECRET_KEY=sk_test_xxx
STRIPE_PUBLISHABLE_KEY=pk_test_xxx
# Optional
SENDGRID_API_KEY= # Leave empty if not using
Recommendations
- Rotate compromised secrets - Any secret found in code or git
- Document all variables - Update .env.example
- Use secret manager - Consider Doppler, Vault, or cloud secrets
- Add pre-commit hook - Prevent secrets from being committed
Focus on security issues first. Provide specific fixes for each problem.