-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
feat(WSTG-CONF-15): add testing for feature flag security bypass #1273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
32064ef
f17c95b
06998be
badbc47
35b8518
6d2c169
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,188 @@ | ||||||
| # Testing for Feature Flag Security Bypass | ||||||
|
|
||||||
| |ID | | ||||||
| |------------| | ||||||
| |WSTG-CONF-15| | ||||||
|
Comment on lines
+3
to
+5
|
||||||
|
|
||||||
| ## Summary | ||||||
|
|
||||||
| Feature flags (also known as feature toggles, feature switches, or feature gates) are a software development technique that allows teams to enable or disable functionality without fully deploying (or exposing) new code. While feature flags provide significant benefits for progressive delivery and A/B testing, they can introduce security vulnerabilities when improperly implemented. | ||||||
|
|
||||||
| Common security issues with feature flags include: | ||||||
|
|
||||||
| - **Client-side manipulation**: Flags evaluated in the browser can be modified by attackers to enable restricted features. | ||||||
| - **Authorization bypass**: Hidden UI elements may still have accessible backend endpoints. | ||||||
| - **Information disclosure**: Flag configurations may leak unreleased features or internal logic. | ||||||
| - **Insecure defaults**: Fallback values when the flag service is unavailable may fail open. | ||||||
| - **Stale flag vulnerabilities**: Unused flags referencing deprecated code paths may contain unpatched vulnerabilities. | ||||||
|
|
||||||
| Modern applications increasingly rely on feature flag services (such as: LaunchDarkly, Split, Flagsmith, ConfigCat) or custom implementations for control roll-outs, making security testing of these mechanisms essential. | ||||||
|
|
||||||
| ## Test Objectives | ||||||
|
|
||||||
| - Identify feature flags that gate security-relevant functionality. | ||||||
| - Assess whether feature flag states can be manipulated client-side. | ||||||
| - Verify that backend authorization is independent of flag state. | ||||||
| - Determine if flag configurations expose sensitive information. | ||||||
| - Evaluate fail-safe behavior when the flag service is unavailable. | ||||||
|
|
||||||
| ## How to Test | ||||||
|
|
||||||
| ### Identify Feature Flags in the Application | ||||||
|
|
||||||
| Search for evidence of feature flag implementations: | ||||||
|
|
||||||
| 1. **Inspect JavaScript bundles** for references to feature flag services or configuration objects: | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it might be better for these to be level 4 headings, with an intro sentence. |
||||||
|
|
||||||
| ```javascript | ||||||
| // Common patterns to search for: | ||||||
|
Comment on lines
+35
to
+38
|
||||||
| featureFlags | ||||||
| featureToggles | ||||||
| flags.isEnabled | ||||||
| LaunchDarkly | ||||||
| splitio | ||||||
| flagsmith | ||||||
| ``` | ||||||
|
|
||||||
| 1. **Monitor network traffic** for requests to feature flag endpoints: | ||||||
|
|
||||||
| ```http | ||||||
| GET /api/features HTTP/1.1 | ||||||
| Host: example.com | ||||||
|
|
||||||
| HTTP/1.1 200 OK | ||||||
| Content-Type: application/json | ||||||
|
|
||||||
| { | ||||||
| "features": { | ||||||
| "new_checkout_flow": true, | ||||||
| "admin_panel_v2": false, | ||||||
| "beta_api": false | ||||||
| } | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| 1. **Examine localStorage and cookies** for cached flag values. | ||||||
|
|
||||||
| ### Test Client-Side Flag Manipulation | ||||||
|
|
||||||
| Attempt to modify flag values to enable restricted features: | ||||||
|
|
||||||
| 1. **Intercept and modify responses**: Use a proxy tool to change flag values from `false` to `true` in API responses. | ||||||
|
|
||||||
| ```http | ||||||
| # Original response | ||||||
| {"admin_mode": false} | ||||||
|
|
||||||
| # Modified response | ||||||
| {"admin_mode": true} | ||||||
| ``` | ||||||
|
|
||||||
| 1. **Modify localStorage**: If flags are cached client-side, change the values directly. | ||||||
|
|
||||||
| ```javascript | ||||||
| // In browser console | ||||||
| localStorage.setItem('featureFlags', JSON.stringify({ | ||||||
| ...JSON.parse(localStorage.getItem('featureFlags')), | ||||||
| restricted_feature: true | ||||||
| })); | ||||||
| ``` | ||||||
|
|
||||||
| 1. **Observe application behavior**: Determine if the application grants access to functionality that should be restricted. | ||||||
|
|
||||||
| ### Verify Backend Authorization Independence | ||||||
|
|
||||||
| Ensure backend endpoints enforce authorization independently of flag state: | ||||||
|
|
||||||
| 1. **Identify hidden endpoints**: Extract API endpoints from JavaScript bundles that are associated with disabled features. | ||||||
|
|
||||||
| ```bash | ||||||
| # Search for API patterns in JS files | ||||||
| grep -oE '/api/v[0-9]+/[a-zA-Z_]+' bundle.js | ||||||
| ``` | ||||||
|
|
||||||
| 1. **Send direct requests**: Attempt to access endpoints for disabled features. | ||||||
|
|
||||||
| ```http | ||||||
| POST /api/admin/users/delete HTTP/1.1 | ||||||
| Host: example.com | ||||||
| Authorization: Bearer <user_token> | ||||||
| Content-Type: application/json | ||||||
|
|
||||||
| {"user_id": "12345"} | ||||||
| ``` | ||||||
|
|
||||||
| 1. **Expected result**: The server should return `403 Forbidden` if the feature is disabled, not just hide the UI. | ||||||
|
||||||
| 1. **Expected result**: The server should return `403 Forbidden` if the feature is disabled, not just hide the UI. | |
| 1. **Expected result**: The server must enforce authorization independently of client-side flag state: unauthorized users receive `401 Unauthorized` or `403 Forbidden` for this endpoint even if they manipulate flags client-side. If the feature is globally disabled by design, the endpoint should remain inaccessible (for example, `404 Not Found` or `403 Forbidden` for all users), rather than only hiding the UI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The guide doesn't need to link to itself as a ref 😀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order for the PDFs etc to generate and link internally properly the file name text needs to be the same as this (or vice versa). So either they both need to be "Testing" or they both need to be "Test"... "Test" seems to be the current file convention.