Feature flags are environment-specific
Why it matters
Feature flags hardcoded in source code or set to the same value across all environments create two distinct risks: debug panels, admin shortcuts, and incomplete features ship to production, and toggling them requires a code change and redeployment rather than a configuration update. OWASP A05 (Security Misconfiguration) and CWE-1188 both flag hardcoded defaults as a misconfiguration class. A debug panel exposed in production can leak stack traces, internal routes, or database query details. A payment feature flag stuck at true in staging that also runs in production will charge real customers for test transactions.
Severity rationale
Medium because hardcoded feature flags allow debug or incomplete features to surface in production, where they can expose internal system details or trigger unintended behavior.
Remediation
Replace hardcoded flag values with environment variable checks or a feature flag service. The flag evaluation must differ between environments — checking only NODE_ENV is sufficient for simple cases; use a service like LaunchDarkly or Unleash for runtime toggling without redeployment.
// BEFORE (wrong)
const DEBUG_MODE = true
// AFTER (correct) — environment variable + NODE_ENV guard
const DEBUG_MODE =
process.env.NODE_ENV !== 'production' &&
process.env.ENABLE_DEBUG === 'true'
// AFTER (correct) — feature flag service
import { isEnabled } from '@unleash/nextjs'
const debugEnabled = await isEnabled('debug-panel')
Verify that every flag evaluates to false in production by running the production config locally and asserting against each flag name.
Detection
-
ID:
feature-flags -
Severity:
medium -
What to look for: Look for feature flag configuration in the codebase. Check if flags are environment-aware (using
process.env.NODE_ENVor environment variable checks). Verify disabled features are not accessible in production (no debug panels, no feature previews, no test routes). -
Pass criteria: Enumerate all feature flags found in the codebase. Feature flags are configured per environment with at least 100% using environment variables or a flag service. Disabled features are not rendered in production. Feature flag state is not hardcoded.
-
Fail criteria: Feature flags are hardcoded in source, or debug/test features are accessible in production.
-
Skip (N/A) when: The project does not use feature flags.
-
Detail on fail:
"Feature flags hardcoded to true for all environments"or"Debug panel accessible in production via /debug route". -
Remediation: Move feature flags to environment configuration:
// BEFORE (wrong) const DEBUG_MODE = true // hardcoded // AFTER (correct) const DEBUG_MODE = process.env.NODE_ENV !== 'production' && process.env.ENABLE_DEBUG === 'true'Or use a feature flag service:
import { getFeatureFlag } from '@launchdarkly/node-server-sdk' const debugEnabled = await getFeatureFlag(client, 'debug-panel', context)
External references
- cwe · CWE-1188 — Initialization of a Resource with an Insecure Default
- owasp:2021 · A05 — Security Misconfiguration
Taxons
History
- 2026-04-18·v1.0.0·Initial import from environment-security·automated