Using the same environment configuration across development, staging, and production means a developer mistake in a test environment can hit production data, a staging webhook fires against live Stripe, or a misconfigured query runs against the production database. CWE-1188 (Use of Hardcoded Default Values) and OWASP A05 both flag shared configurations as a misconfiguration risk. NIST CM-6 requires controlled configuration management — shared .env files with no environment separation make that impossible to enforce. Beyond security, shared configs make incident response harder: you cannot revoke a staging credential without also revoking the production one.
High because shared environment configs mean a misconfiguration, test, or breach in any environment can directly impact production systems and data.
Create distinct configuration files for each environment and load them based on NODE_ENV. Each file must use environment-specific credentials, endpoints, and API keys — never the same values.
.env.development # local dev: localhost DB, Stripe test keys, sandbox API endpoints
.env.staging # staging server: staging DB, Stripe test keys, staging endpoints
.env.production # production server: production DB, Stripe live keys, production endpoints
// At server startup
import dotenv from 'dotenv'
dotenv.config({ path: `.env.${process.env.NODE_ENV ?? 'development'}` })
All three files go in .gitignore. Maintain a .env.example with placeholder values for each variable so new developers know what to fill in.
ID: environment-security.secrets-management.env-separation
Severity: high
What to look for: Check for presence of environment-specific configuration files or environment variable patterns. Look for .env.development, .env.staging, .env.production, or similar. Check that each environment has distinct API endpoints, database connections, and API keys.
Pass criteria: Count all environment-specific config files found. Each environment (development, staging, production) must have its own configuration -- at least 2 distinct environment configs must exist. Databases, API keys, and endpoints differ per environment.
Fail criteria: All environments share the same .env file or configuration, or no environment separation is evident.
Skip (N/A) when: The project is single-environment only (e.g., local development only, no staging or production).
Detail on fail: "Only .env file found; no .env.development, .env.staging, .env.production separation" or "All environments point to the same database and API endpoints".
Remediation: Create environment-specific config files:
.env.development # local dev, localhost, test keys
.env.staging # staging server, staging API endpoints, staging DB
.env.production # production server, production endpoints, production DB
Load the appropriate file based on NODE_ENV:
import dotenv from 'dotenv'
dotenv.config({ path: `.env.${process.env.NODE_ENV}` })