Restrict Features with Permissions-Policy
Send a Permissions-Policy header that disables powerful browser features the app does not use, so injected or third-party code cannot call them.
Task
Lock down camera, microphone, geolocation, and other features the application does not need.
When to use this
Any script on the page, including a compromised third-party one, can request camera or geolocation because no policy restricts them.
Prerequisites
- Control over response headers
- An inventory of features the app uses
Steps
1. List the browser features the app genuinely needs.
Expected output: You know what to allow.
2. Send a Permissions-Policy disabling everything else by default.
Expected output: Unused powerful APIs are unavailable.
3. When embedding, set allow attributes on iframes for only the needed features.
Expected output: Embedded content gets the minimum capability.
4. Monitor console warnings for blocked features that legitimately need enabling.
curl -sI https://app.example.com | grep -i permissions-policyExpected output: You can add exceptions without guesswork.
Troubleshooting
Problem
A needed feature is blocked
Solution
Add only the specific feature to the allow list; do not disable the header entirely.
Problem
Third-party iframe broken
Solution
Grant the feature on that iframe via the allow attribute rather than globally.
Limitations
- Permissions-Policy support and feature names vary by browser, so some directives may be ignored.
- It restricts feature access but does not by itself prevent all data exfiltration.
Context
Lock down camera, microphone, geolocation, and other features the application does not need. Any script on the page, including a compromised third-party one, can request camera or geolocation because no policy restricts them.
Steps
- List the browser features the app genuinely needs. Expected: You know what to allow.
- Send a Permissions-Policy disabling everything else by default. Expected: Unused powerful APIs are unavailable.
- When embedding, set allow attributes on iframes for only the needed features. Expected: Embedded content gets the minimum capability.
- Monitor console warnings for blocked features that legitimately need enabling. Expected: You can add exceptions without guesswork.
res.setHeader('Permissions-Policy',
'camera=(), microphone=(), geolocation=(), payment=(), usb=()');
Verify
- You know what to allow.
- Unused powerful APIs are unavailable.
- Embedded content gets the minimum capability.
- You can add exceptions without guesswork.
Limits
- Permissions-Policy support and feature names vary by browser, so some directives may be ignored.
- It restricts feature access but does not by itself prevent all data exfiltration.