Permissions-Policy Configuration Issues
What This Means
Permissions-Policy (formerly Feature-Policy) is an HTTP header that allows websites to control which browser features and APIs can be used by the page and embedded iframes. Misconfiguration or absence of this header can lead to:
- Unauthorized use of sensitive APIs (camera, microphone, geolocation)
- Third-party scripts accessing features without consent
- Privacy violations from embedded content
- Unexpected battery drain from background features
- Security vulnerabilities in cross-origin iframes
- Failed security audits and compliance issues
Proper Permissions-Policy configuration is essential for security, privacy, and performance.
How to Diagnose
Check Current Policy
# Check if Permissions-Policy header is present
curl -I https://example.com | grep -i permissions-policy
# Example response:
# Permissions-Policy: camera=(), microphone=(), geolocation=(self)
Browser DevTools
- Open Network tab and inspect response headers
- Look for
Permissions-Policyheader - Check Console for policy violation warnings
JavaScript Feature Detection
// Check if feature is allowed
if (document.featurePolicy) {
console.log('Camera allowed:',
document.featurePolicy.allowsFeature('camera'));
console.log('Geolocation allowed:',
document.featurePolicy.allowsFeature('geolocation'));
// List all allowed features
document.featurePolicy.allowedFeatures().forEach(feature => {
console.log(feature);
});
}
Online Tools
- Security Headers - Check header configuration
- Mozilla Observatory - Security scan
- Chrome DevTools Console - Shows policy violations
Common Issues
- Missing Permissions-Policy header entirely
- Overly permissive policies allowing all features
- Blocking features the site actually needs
- Not restricting third-party iframe permissions
- Conflicting policies between headers and iframe attributes
General Fixes
Set restrictive default policy - Block all features by default, allow only what's needed
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=(), ambient-light-sensor=()Allow specific features for same-origin
Permissions-Policy: camera=(self), microphone=(self), geolocation=(self)Allow features for trusted origins
Permissions-Policy: camera=(self "https://trusted-domain.com"), payment=(self "https://payment-provider.com")Use wildcard cautiously - Only for non-sensitive features
Permissions-Policy: fullscreen=*, picture-in-picture=(self)Configure in web server
# nginx add_header Permissions-Policy "camera=(), microphone=(), geolocation=(self)";# Apache Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(self)"Control iframe permissions - Use allow attribute on iframes
<iframe src="https://example.com" allow="camera 'none'; microphone 'none'; geolocation 'self'"> </iframe>Common feature directives
camera- Camera accessmicrophone- Microphone accessgeolocation- Location datapayment- Payment Request APIautoplay- Media autoplayfullscreen- Fullscreen modeaccelerometer,gyroscope,magnetometer- Motion sensorsusb,bluetooth- Device APIs
Test before deploying - Ensure needed features still work
// Test geolocation navigator.geolocation.getCurrentPosition( (position) => console.log('Success:', position), (error) => console.error('Blocked by policy:', error) );
Platform-Specific Guides
| Platform | Guide |
|---|---|
| nginx | Header Configuration |
| Apache | mod_headers |
| Next.js | Security Headers |
| Cloudflare | Transform Rules |
| Netlify | Custom Headers |