Configuration management separates environment-specific values from code
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:
// 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:
// 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 — External Control of System or Configuration Setting
- owasp:2021 · A05 — Security Misconfiguration
- nist:rev5 · CM-6 — Configuration Settings
Taxons
History
- 2026-04-18·v1.0.0·Initial import from security-hardening·automated