What it is
Permissions-Policy (formerly Feature-Policy) is an HTTP response header that tells the browser which features and APIs your page can use. You can disable or limit access to camera, microphone, geolocation, payment request, and other capabilities for your page and any iframes it embeds.
Why it matters
If you don't set Permissions-Policy, the browser's default behavior applies. Restricting features you don't need reduces the impact of bugs or malicious third-party content. It also makes it clear to auditors and scanners that you've thought about which capabilities your app actually uses.
How it is exploited
An XSS payload or a compromised third-party widget on your page calls navigator.geolocation.getCurrentPosition or navigator.mediaDevices.getUserMedia. With no Permissions-Policy, the browser prompts the user with your origin's name, so the consent dialog looks legitimate and the attacker harvests location or camera access. A locked-down policy blocks the call before the prompt ever appears.
How to fix it
- Decide which features to allow. List the browser features your app uses. For most content sites, you can disable camera, microphone, geolocation, and similar. For apps that need one of these, allow it only for your origin or specific iframes.
- Add the header. Send Permissions-Policy on every response. Use a comma-separated list of feature names and allowlists. For example, to disable several features: camera=(), microphone=(), geolocation=(). Use 'self' or specific origins if you need to allow a feature.
- Test your app. After deploying, confirm that any feature you rely on (e.g. payment request) still works. If something breaks, add that feature with the right allowlist.
- Verify. Run Barrion's Permissions-Policy check or inspect the response header to confirm the policy is present and correct.
Examples by platform
Nginx
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;Apache
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()"How to verify the fix
Confirm the Permissions-Policy header is present in HTTPS responses:
curl -sI https://example.com | grep -i permissions-policy