# Configuration management separates environment-specific values from code

- **Pattern:** `ab-002393` (`security-hardening.secrets-config.config-separation`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002393
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002393)

## Why it matters

Hardcoded environment-specific values — production database URLs, service endpoints, feature flag literals — mean configuration changes require code changes and redeployments, increasing the chance of accidental environment cross-contamination. CWE-15 (External Control of System or Configuration Setting) and OWASP A05 (Security Misconfiguration) both flag this pattern. NIST 800-53 CM-6 requires configuration management to separate configuration from code. A developer testing against a staging endpoint that is hardcoded in the file may accidentally push a commit that hits production services in a different environment.

## Severity rationale

Low because hardcoded config values are primarily an operational risk — they create deployment fragility and increase the chance of accidental production access from non-production code.

## Remediation

Centralize all environment-specific values behind `process.env` and validate required variables at startup:

```ts
// lib/config.ts
const config = {
  apiUrl: process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:3001',
  dbUrl: process.env.DATABASE_URL,
  featureNewDashboard: process.env.FEATURE_NEW_DASHBOARD === 'true',
} as const

if (typeof window === 'undefined' && !config.dbUrl) {
  throw new Error('DATABASE_URL is required')
}

export default config
```

Remove any string literals that embed production hostnames, service URLs, or environment-specific feature toggles from source files. Use `.env.example` with placeholder values to document all required variables.

## Detection

- **ID:** `config-separation`
- **Severity:** `low`
- **What to look for:** Enumerate every configuration value that differs between environments (dev, staging, production). For each, check whether the application properly separates environment-specific configuration (database URLs, feature flags, service endpoints, log levels) from application code. Look for hardcoded production URLs, environment-specific conditionals with literal values, or feature toggles implemented as code constants instead of environment variables.
- **Pass criteria:** Environment-specific values (endpoints, feature flags, service URLs, log levels) are loaded from environment variables or a configuration service. Code doesn't embed environment-specific string literals. Different environments (dev, staging, prod) use different values without code changes — 100% of environment-specific values must be externalized. Report: "X environment-specific configs found, all Y separated from code."
- **Fail criteria:** Production database URLs, service endpoints, or feature flag values are hardcoded in source files. Different environments require code changes to switch.
- **Skip (N/A) when:** Never — all non-trivial applications have environment-specific configuration.
- **Detail on fail:** `"Production API endpoint hardcoded as a string literal in lib/client.ts"` or `"Feature flags implemented as constants in config.ts with production values committed — requires code change to enable/disable"`
- **Remediation:** Externalize all environment-specific values:

  ```ts
  // lib/config.ts — centralized config with validation
  const config = {
    apiUrl: process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:3001',
    dbUrl: process.env.DATABASE_URL,
    logLevel: process.env.LOG_LEVEL ?? 'info',
    featureFlags: {
      newDashboard: process.env.FEATURE_NEW_DASHBOARD === 'true',
    },
  } as const

  // Validate required server-side vars at startup
  if (typeof window === 'undefined') {
    if (!config.dbUrl) throw new Error('DATABASE_URL is required')
  }

  export default config
  ```

## External references

- cwe CWE-15
- owasp A05
- nist CM-6

Taxons: operational-readiness

HTML version: https://auditbuffet.com/patterns/ab-002393
