Permissions-Policy: disable the browser features your site never uses
· permissions-policy · security-headers · feature-policy · browser-features · privacy
permissions-policysecurity-headersfeature-policybrowser-featuresprivacyThe 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.
Further reading
- Security headers: a practical guide to the ones that matter
- Which Referrer-Policy should you use?
- "Refused to load": reading and fixing CSP violations
- W3C Permissions Policy specification (the standard that superseded Feature Policy)