Feature Flags as Access Control
The feature flag pattern started as a way to decouple deployment from release β code is shipped to production but kept dormant behind a flag. Over time, flags evolved from simple boolean toggles to sophisticated targeting systems that evaluate user attributes, organisation tiers, geographic regions, and custom rules to determine who gets access to which code paths.
That sophistication means flags now frequently govern business-critical access decisions: which users can access beta APIs, which organisations can use premium features, which operators can see the admin dashboard, which accounts have elevated rate limits. These are access control decisions. But they live in a flag management system that typically has weaker governance than the application's main authorisation layer β fewer access reviews, no security testing, and limited audit logging of who changed what rule and when.
The governance gap: Your IAM policies, RBAC rules, and database row-level security are reviewed by security teams and subject to change control. Your feature flag targeting rules in LaunchDarkly or Unleash are often modified by any developer with portal access, without review, with no alerting on changes that grant broad access.
Client-Side Flag Exposure
Client-side SDK integrations β used in web and mobile applications β require the application to fetch flag evaluation data from the flag management service. In many implementations, the full flag configuration is delivered to the client: flag names, targeting rules, and sometimes the evaluated values for all flags in the user's context. This creates several security issues.
Flag names reveal product roadmap: a flag named enable-sso-enterprise or new-payment-processor tells a competitor β or an attacker scoping an engagement β exactly what is being built. More critically, if the flag evaluation logic is exposed to the client, an attacker may be able to understand the targeting rules and craft a context that evaluates to true for a flag they should not have access to.
Flag Manipulation Attacks
If flag evaluation is performed client-side or if the server trusts client-supplied context attributes without server-side validation, an attacker can manipulate the evaluation context to gain access to restricted flags. Common examples include: including "beta": true in a client-supplied context to pass a targeting rule that enables beta features; setting "plan": "enterprise" to access premium functionality; or adding "role": "admin" to trigger an admin feature flag that does not have server-side access control backing it up.
The vulnerability class is the same as any client-controlled authorisation decision: if the server does not independently verify the claim, the claim can be forged. Feature flag systems that trust any attribute the client sends are vulnerable to escalation attacks even if the flag evaluation logic itself is correct.
Server-side evaluation is mandatory for security-relevant flags: Flags that control access to sensitive functionality must be evaluated server-side using attributes that the application derives from authenticated session state β not attributes supplied by the client.
Incomplete Code Behind Flags
Dark-launched code is production code that has not undergone the same security scrutiny as released features. Security reviews, penetration tests, and threat modelling typically target released functionality. Code behind a flag β especially one expected to ship "in a few sprints" β is often not reviewed with the same rigour. This creates a situation where production systems contain unreviewed, potentially vulnerable code paths that can be activated by anyone who can modify flag state.
SQL injection vulnerabilities in unreleased query builders, IDOR issues in new API endpoints, and missing authentication checks in admin features that are "not live yet" are all examples of vulnerabilities that exist in production systems but are invisible to security testing because they are behind a flag. When the flag is activated β whether legitimately or by an attacker β those vulnerabilities become exploitable.
SDK Key Exposure and Flag Modification
Flag management SDKs require API keys for authentication. Client-side SDK keys are intentionally public β they are embedded in JavaScript bundles and mobile apps. However, server-side SDK keys, which allow flag evaluation and in some configurations flag modification, are often treated with insufficient care. Server-side SDK keys found in environment variables, committed to repositories, or exposed in error responses give attackers the ability to evaluate flags as any user context they choose and, if write permissions are granted, to modify flag targeting rules directly.
Even read-only SDK keys allow an attacker to enumerate every flag in the project, evaluate flags in arbitrary user contexts, and understand the full targeting rule logic β information that can guide both direct attacks and social engineering.
Feature Flag Governance
- Classify flags by security impact: Distinguish between flags that are purely cosmetic (UI changes) and flags that control access to functionality, bypass rate limits, or modify security-relevant behaviour. Apply approval workflows and audit requirements to security-relevant flags.
- Never use client-supplied context for security decisions: All attributes used in flag targeting rules that govern access control must come from server-verified session state. Never trust a client-supplied
role,plan, orisAdminattribute. - Audit flag changes with the same rigour as access control changes: Enable audit logging on your flag management platform. Alert on changes to flags that control security-sensitive code paths. Require change approval for flag modifications in production.
- Security-test dark-launched code: Include code behind flags in your security testing scope even before launch. A vulnerability that exists in production code is exploitable once the flag is activated.
- Protect server-side SDK keys: Store server-side SDK keys in your secrets management system. Rotate them on any suspected exposure. Never include them in client-side bundles or version control.
- Enforce a flag lifecycle policy: Flags accumulate over time. Old flags with permissive targeting rules that were created for testing and forgotten are a persistent attack surface. Require flag owners and expiry dates, and automatically disable flags that have not been reviewed.