SEC-002 recommended Secret Storage

Secrets Loaded into Process Environment

Secrets injected into process environment at startup, not read from files at runtime

Question to ask

"Would a crash dump expose any credentials?"

What to check

  • Application reads from process.env / os.environ
  • Centralized config with env validation at startup
  • Deployment passes env vars (not files)
  • dotenv only used for local development

Pass criteria

  • Application reads secrets via environment variables
  • Secrets injected at deploy time (not read from files)
  • Centralized config validates required env vars at startup
  • dotenv dev-only, not used in production

Verification guide

Severity: Critical

Secrets should be injected into the process environment at startup, not read from files at runtime. The application reads from process.env / os.environ / equivalent.

Check automatically:

  1. Check application reads from environment variables:
# Node.js - process.env usage
grep -rE "process\.env\." src/ lib/ app/ --include="*.ts" --include="*.js" 2>/dev/null | head -20

# Python - os.environ or os.getenv
grep -rE "os\.environ|os\.getenv" src/ app/ --include="*.py" 2>/dev/null | head -20

# Go - os.Getenv
grep -rE "os\.Getenv" . --include="*.go" 2>/dev/null | head -20
  1. Check for proper config patterns (centralized config loading):
# Config file that loads from env
ls -la src/config* lib/config* app/config* config/ 2>/dev/null

# Environment validation at startup (good pattern)
grep -rE "required.*env|validateEnv|envalid|zod.*env|env-var" src/ lib/ 2>/dev/null
  1. Check deployment passes env vars (not files):
# Kubernetes env injection
grep -rE "env:|envFrom:" k8s/ kubernetes/ manifests/ 2>/dev/null

# Docker Compose environment
grep -rE "environment:" docker-compose*.yml 2>/dev/null

# Systemd service (should use Environment= or EnvironmentFile=)
grep -rE "Environment=|EnvironmentFile=" *.service 2>/dev/null
  1. Check for anti-patterns (reading secrets from files at runtime):
# Reading .env files in production code (anti-pattern)
grep -rE "dotenv\.config|load_dotenv|godotenv" src/ lib/ app/ 2>/dev/null

# Direct file reads for secrets
grep -rE "readFileSync.*secret|readFile.*key\.pem|readFile.*\.env" src/ lib/ 2>/dev/null

Ask user:

  • "Does your app read secrets from environment variables or config files?"
  • "Is dotenv/similar used in production?" (acceptable for local dev only)

Cross-reference with:

  • SEC-001 (secret manager - source of the env vars)
  • SEC-003 (not stored on filesystem)
  • ENV-002 (environment tiers)

Pass criteria:

  • Application reads secrets via process.env / os.environ / equivalent
  • Secrets injected into environment at deploy time (not read from files)
  • Centralized config pattern validates required env vars at startup
  • dotenv only used for local development, not production

Fail criteria:

  • Secrets read from filesystem in production
  • No environment variable usage - hardcoded or file-based
  • dotenv used in production to load .env files from disk

Evidence to capture:

  • How secrets reach the process (env injection method)
  • Config pattern used (centralized validation or scattered)
  • Whether dotenv is dev-only or also used in prod

Section

29. Secrets Management

Code Quality & Architecture