Feature Flags and Dark Launches: Authorization Bypasses Hunters Miss
Product teams ship unfinished UI behind flags. Security teams assume “hidden” means “denied.” Hunters know the API often exists either way — the flag only controls whether React mounts the button.
Dark launches, beta cohorts, and “staff only” toggles are authorization decisions dressed as product config. Treat them like roles.
Client gates are not access control
If the browser checks flags.newBilling === true before showing a route, send the API calls anyway. Copy paths from JS bundles, source maps, or mobile apps. Many “disabled” features return full JSON for any authenticated user.
Look for:
/api/internal/...or/api/v2/beta/...routes referenced in webpack chunks- Query params like
?beta=1,?ff_new_dashboard=true - Cookies or localStorage keys the SPA reads for entitlements
- Headers such as
X-Enable-Feature,X-Dark-Launch,X-Staff-Mode
Flipping a client flag that the server never validates is a classic medium/high when the unlocked action is sensitive.
Server-side flag mistakes
Some backends do check a flag service — then trust the client’s reported cohort. Others gate the happy path and leave debug endpoints ungated. Pattern hunt:
- Enable a flag for account A (legitimately or via a weak admin toggle).
- Diff traffic against account B without the flag.
- Replay B against A’s newly visible endpoints.
- Try forcing flag evaluation with body fields:
features[],entitlements,plan.
Shared flag keys across tenants (“enable_export for everyone in region”) can widen blast radius when combined with weak object auth.
Dark launch and preview environments
Preview deploys, per-PR apps, and “early access” hosts often reuse production identity providers with looser rules. Check whether:
- Staging flags leak production data connectors
- A preview cookie unlocks production APIs
- Staff impersonation flags remain on customer-facing hosts
Scope carefully — some programs exclude previews. When in-scope, these hosts are gold for unfinished authZ.
Impact framing
Tie the flag to a concrete privilege: refund API, cross-tenant analytics, PII export, destructive admin actions. “I saw a beta button” is not a bug. “Unauthenticated/flagless user invoked POST /api/billing/credit” is.
Mobile builds and partner portals often evaluate a different flag project than the main web app. Diff their configs; a kill-switch that exists only on web leaves the same API open from the other client.
Proof tips
Use two users: flagged and unflagged. Show identical requests succeeding for both, or succeeding after you forge a header the UI would have set. Avoid demanding production flag changes from the triage team; reproduce with client-side or public beta signals when possible.
Hardening notes for reports
Recommend evaluating flags only on the server, binding flags to subject identity (not request headers), and denying by default when the flag service is unreachable. Ship authorization tests that call beta routes without entitlements.
Guidance stacks well with OWASP authorization schema testing and CWE-862 (missing authorization).
If product can hide a feature with a boolean, security still has to refuse the API. Treat every new flag like a new permission until the server proves otherwise.