Domain.Posture
← blog

Permissions-Policy: disable the browser features your site never uses

· permissions-policy · security-headers · feature-policy · browser-features · privacy

permissions-policysecurity-headersfeature-policybrowser-featuresprivacy

The Permissions-Policy response header lets a site declare which powerful browser features — camera, microphone, geolocation, payment, and others — the page and any iframes it embeds are allowed to use. It replaced the older Feature-Policy header (same idea, new name and slightly different syntax). A practical baseline is to disable every feature your site does not actually call, which shrinks the surface a compromised script or a sketchy embedded iframe can abuse. It is a hardening control, not an authentication or content-injection defence — that is still CSP's job.

A recommended baseline

If your site does not use the camera, microphone, or location, turn them off explicitly. An empty allowlist () means "no origin, not even this page":

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

That header denies those features to your own page and to every iframe. interest-cohort=() opts the page out of the legacy FLoC trial; it is harmless to keep even though FLoC itself was discontinued. Add or remove features to match what your application genuinely needs — there is no benefit to listing features you do not control.

If a feature is needed, allow only the origin that needs it rather than leaving it open. A video-call page that uses the camera and mic on its own origin would write:

Permissions-Policy: camera=(self), microphone=(self), geolocation=()

The allowlist syntax

Each directive is feature=<allowlist>. The allowlist is a space-separated list inside parentheses:

  • () — empty list. The feature is disabled for everyone, including this page.
  • (self) — the feature is allowed for the current origin only. Same-origin iframes inherit it; cross-origin ones do not.
  • * — allowed for all origins (this page and any iframe). Use sparingly.
  • (self "https://embed.example.com") — allowed for this origin plus the named cross-origin embed. Origins are quoted and space-separated.

To let a specific third-party iframe use a feature, name its origin in the parent's header and grant it on the iframe element with the allow attribute, e.g. allow="camera". Both the document policy and the iframe attribute must permit it.

What it does and does not protect

Permissions-Policy reduces abuse and accidental exposure: a third-party tag cannot silently prompt for geolocation, an embedded widget cannot reach for the microphone, and a compromised dependency loses access to capabilities you never enabled. That is real defence-in-depth.

It is not a substitute for a Content-Security-Policy. CSP governs what code and content can load and execute; Permissions-Policy governs which device and browser capabilities that code may reach once it is running. They cover different layers — ship both. The header is also not enforced retroactively on already-granted permissions in some edge cases, so treat it as a default-deny posture you set from the start.

Check your security headers →

Further reading

Frequently asked questions

What is the Permissions-Policy header and why do I need it?
Permissions-Policy controls which powerful browser features—camera, microphone, geolocation, payment—your page and its iframes can use. Disable features you don't need to reduce the risk of compromised scripts or sketchy embedded iframes abusing them.
How do I disable browser features with Permissions-Policy?
Use an empty allowlist `()` for each feature you don't use. For example: `Permissions-Policy: camera=(), microphone=(), geolocation=()` denies those features to your page and all iframes.
Can I allow specific iframes to use camera or microphone?
Yes. List the iframe's origin in the header (e.g., `camera=(self "https://embed.example.com")`) and add the `allow` attribute to the iframe element (e.g., `allow="camera"`). Both the header and iframe attribute must permit it.
Is Permissions-Policy a substitute for Content-Security-Policy?
No. CSP controls what code can load and execute; Permissions-Policy controls which device and browser capabilities that code can reach. They protect different layers—use both.