Skip to main content
All fixes

SSL, TLS, security headers

Set Permissions-Policy to restrict browser feature access

Without Permissions-Policy, embedded iframes and scripts can use camera, mic, geolocation, and payment APIs. Disable unused features explicitly.

What's happening

Permissions-Policy (formerly Feature-Policy) is an HTTP response header that controls which browser features the page and its embedded frames are allowed to use — camera, microphone, geolocation, payment requests, accelerometer, USB, fullscreen, autoplay, and dozens more. Without it, every feature is available to the page and (per default policy) to same-origin frames; cross-origin frames must allowlist via the iframe allow attribute.

An attacker who manages to inject an iframe or compromise a third-party widget can quietly request access to features the user did not expect. Permissions-Policy lets you declare a security baseline at the response level: 'this page never needs camera, geolocation, or payment, and neither does anything embedded in it'.

The fix is to enumerate the features the page actually uses and disable the rest. The header syntax is verbose but mechanical, and tooling like permissionspolicy.com generates valid strings from a checkbox UI.

Why it matters

Compromised third-party scripts cannot request features the policy forbids. A poisoned analytics script that tries to access geolocation will be blocked at the browser level.

Privacy-conscious users who run security extensions and audit headers expect Permissions-Policy on production sites; missing the header is a visible signal.

Mozilla Observatory and SecurityHeaders.com flag the missing header. Some bug-bounty programs accept missing Permissions-Policy as a low-severity finding.

Common causes

  • Web server has never set the header.
  • An older Feature-Policy header is set but Permissions-Policy is missing — modern browsers use Permissions-Policy.
  • A blanket allowlist (* was set during development and never tightened.
  • Per-route policies disagree, leaving features available on routes that should not have them.
  • A reverse proxy or CDN strips response headers it does not recognize.

Detect this on your site

Run a quick scan with the Full Site Audit. The tool surfaces this exact issue with the records and context needed to apply the fix below.

Open Full Site Audit

How to fix it

  1. 1

    Inventory features actually used

    Open the production site in Chrome and use Lighthouse or chrome://flags/#document-policy to list the features each page uses. Most marketing pages use no special features. Apps may need camera, geolocation, or payment — be honest about which.

  2. 2

    Generate a deny-by-default policy

    Use the helper at permissionspolicy.com or the Mozilla docs page to build a header value. Default position: every feature set to () (deny everywhere). Open up only what you actually need, e.g. camera=(self) for a video-call page.

  3. 3

    Set the header in nginx

    Add add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()" always;. Note the empty parens for 'deny'. Reload nginx.

  4. 4

    Set the header in Apache

    Add Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()" to the VirtualHost or.htaccess. Reload Apache.

  5. 5

    Allow features per route where needed

    On a video-call route, override with Permissions-Policy: camera=(self), microphone=(self). In Next.js, set it via middleware on the matching path. The route-level header replaces the global one.

  6. 6

    Test with Chrome's permission policy panel

    Open DevTools → Application → Frame details → Permissions Policy. Each disabled feature shows 'denied by HTTP header'. Test interactive routes by trying to call navigator.mediaDevices.getUserMedia() from the console — it should reject.

Example

Permissions-Policy: accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()

Deny-by-default policy for marketing and content sites

Frequently asked

interest-cohort controlled Google's FLoC behavioral-targeting experiment. Although Google replaced FLoC with Topics API the directive remains a public statement that the site does not opt into ad-targeting cohorts. Many privacy-focused sites continue to set it for signaling.

No. Every browser that supports Feature-Policy also supports Permissions-Policy as of 2022. Set Permissions-Policy only. Some scanners still ask for Feature-Policy; ignore those.

Related fixes