Web Security

What is Permissions-Policy and How Does It Enhance Security?

Learn about the Permissions-Policy security header, how it controls browser features and APIs, and best practices for implementing it in modern web applications.

By Inventive HQ Team

What is Permissions-Policy?

Permissions-Policy is an HTTP response header that lets a website declare exactly which powerful browser features — camera, microphone, geolocation, payment, USB, and dozens more — are allowed to run on the page and inside its iframes. It works as an allowlist: every listed feature is set to an origin scope (nobody, your own origin, or named third parties), and anything you do not enable stays off. Formerly called Feature-Policy, the header narrows what a compromised or malicious script can reach, so even if attacker code executes on your page it cannot silently turn on the webcam or read the visitor's location.

That is the summary an AI overview will give you. What it can't give you is the exact directive-to-feature mapping, the syntax that changed when Feature-Policy was renamed, and a live tool to check your own header — all of which are below.

How Permissions-Policy gates browser feature requests Scripts on a page send feature requests toward a Permissions-Policy gate. Requests for features set to empty parentheses are denied, while a request scoped to self is allowed through to the browser API. Permissions-Policy as an allowlist gate Your page & scripts camera request payment request geolocation (self) 3rd-party ad script Permissions-Policy Browser APIs camera=() denied payment=() denied geolocation=(self) allowed blocked

Want to audit your security headers? Try our free Security Headers Analyzer to check your Permissions-Policy and other security headers instantly.

Loading interactive tool...

Feature-to-Directive Reference: What Each Permissions-Policy Directive Controls

Each browser capability maps to a named directive. Set the directive to () to disable it everywhere, (self) to allow only your own origin, (self "https://partner.com") to add a named third party, or * to allow all origins (rarely a good idea). The table below covers the directives most sites should decide on explicitly.

Browser featurePermissions-Policy directiveTypical recommended valueWhy restrict it
Cameracameracamera=()Prevents silent webcam capture by compromised scripts
Microphonemicrophonemicrophone=()Prevents silent audio recording
Locationgeolocationgeolocation=()Stops location tracking most sites never need
Payment Request APIpaymentpayment=()Blocks rogue payment prompts unless you take payments
USB devicesusbusb=()Denies direct access to connected USB hardware
Fullscreenfullscreenfullscreen=(self)Limits fullscreen takeover to your own origin
Accelerometeraccelerometeraccelerometer=()Blocks motion sensing used for device fingerprinting
Gyroscopegyroscopegyroscope=()Same fingerprinting/orientation risk as accelerometer
Magnetometermagnetometermagnetometer=()Prevents compass/orientation surveillance
Autoplayautoplayautoplay=(self)Restricts auto-playing media to your origin
Clipboard writeclipboard-writeclipboard-write=(self)Limits programmatic clipboard writes
Screen wake lockscreen-wake-lockscreen-wake-lock=()Denies keep-screen-awake unless needed

A restrictive starting header that turns off everything sensitive and lets only geolocation run on your own origin looks like this:

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

Understanding the Evolution from Feature-Policy to Permissions-Policy

The Permissions-Policy header represents the modern evolution of what was previously called the Feature-Policy header. The naming change reflects a broader shift in how the web security community thinks about browser capabilities. Rather than thinking about "features," the industry now conceptualizes them as "permissions"—capabilities that require user authorization and should be actively managed by developers.

This semantic shift is important because it reflects a security-first mindset. Features are things you might casually use. Permissions are things that grant access to sensitive data or hardware. By renaming the header, the standards bodies reinforced that developers should treat these capabilities as security-critical rather than as features to enable casually.

The syntax changed along with the name. Feature-Policy used a semicolon-separated list with quoted keywords, while Permissions-Policy uses a structured, comma-separated format with parentheses:

Feature-Policy:     geolocation 'self' https://example.com; microphone 'none'
Permissions-Policy: geolocation=(self "https://example.com"), microphone=()

Note the mapping: the keyword 'none' becomes empty parentheses (), 'self' becomes the token self, and each directive is now joined by commas rather than semicolons. If you are migrating an old header, translate every directive rather than copying it verbatim.

How Permissions-Policy Works: The Allowlist Approach

Permissions-Policy operates on an allowlist principle: you explicitly declare which origins are allowed to use each browser capability. By default, many modern capabilities are restricted, though this behavior varies across browsers and has evolved as security practices have improved.

A Permissions-Policy header might look like:

Permissions-Policy: geolocation=(), camera=(self "https://trusted-partner.com"), microphone=*

This example indicates:

  • geolocation=() - Geolocation is disabled completely, even by the site itself
  • camera=(self "https://trusted-partner.com") - Camera access allowed only for the current origin and one trusted partner
  • microphone=* - Microphone allowed from any origin (not recommended, but technically valid)

The flexibility of Permissions-Policy allows precise control over each capability. Common directives include camera, microphone, geolocation, payment, usb, magnetometer, accelerometer, and dozens more as new browser capabilities are introduced.

Reducing Attack Surface Through Explicit Denial

The primary security benefit of Permissions-Policy is attack surface reduction through explicit denial. If a malicious script somehow executes on your website (through a compromised dependency, third-party ad network, or other injection vulnerability), Permissions-Policy prevents that script from accessing sensitive APIs even if the script tries to use them.

Consider a scenario where a third-party advertisement script is compromised and attempts to access a user's camera or microphone. Without Permissions-Policy, this attack could succeed, capturing video or audio without the user's knowledge. With Permissions-Policy restricting camera and microphone access, the browser simply denies the request, regardless of what the script attempts.

This is a defense-in-depth principle: you assume compromise might occur and layer your defenses so that even if one defense fails, others remain intact. A Content Security Policy (CSP) might prevent the malicious script from executing certain operations, but Permissions-Policy provides an additional layer that prevents access to powerful capabilities at the browser level.

Advertisement

Common Permissions Worth Restricting

Certain permissions are particularly sensitive and should be restricted unless your application genuinely requires them:

Geolocation - Few websites actually need user location data. If your application doesn't provide location-based features, setting geolocation=() prevents any script from attempting location tracking. This is one of the most recommended restrictions.

Camera and Microphone - These hardware access permissions represent some of the most invasive capabilities. Even legitimate uses (video conferencing, voice calls) should restrict these to the same origin only. Third-party services that require camera/microphone access can be allowed explicitly, but only specific trusted origins.

Payment Request API - The payment API allows sites to request sensitive payment information. Unless your application actually processes payments, set payment=() to prevent any script from attempting payment requests.

USB and Serial - These APIs grant access to hardware directly connected to the user's device. Unless your application specifically works with USB or serial devices, restrict these completely.

Sensors - Accelerometer, gyroscope, and magnetometer access can reveal user device movement and orientation, potentially enabling surveillance. Restrict these unless your application genuinely needs them.

Third-Party Script Management

One of the most important use cases for Permissions-Policy involves third-party scripts: analytics providers, ad networks, social media embeds, and other external content. These third parties should only have access to the specific capabilities they need.

An analytics script doesn't need camera, microphone, or payment access. An ad network might request geolocation to serve location-based ads, but this should be an explicit choice the website owner makes. By using Permissions-Policy to restrict third-party scripts, you ensure they can't exceed their intended scope even if they behave maliciously or are compromised.

For example, if you include a third-party video embed from a trusted provider, you might use:

Permissions-Policy: camera=(self "https://video-provider.com"), microphone=(self "https://video-provider.com")

This allows the video provider to access camera and microphone only for their specific origin, not for any arbitrary third party.

Cross-Origin Embedding Protection

Permissions-Policy also controls what capabilities are available when your site is embedded in an iframe on another domain. This is crucial for preventing unauthorized access to sensitive capabilities through embedded content.

If your application provides a widget that other websites embed, you can use Permissions-Policy to restrict which capabilities the embedding site can trigger. For instance, if your widget is embedded as an iframe, the parent site cannot trigger camera access through the embedded frame unless you explicitly allow it.

This becomes particularly important if your embedded widget is placed on untrusted third-party sites. The Permissions-Policy header on your widget ensures that regardless of where it's embedded, the embedding site cannot exceed the permissions you've explicitly granted.

Browser Compatibility and Rollout Strategy

Permissions-Policy has widespread but not universal browser support. All major browsers (Chrome, Firefox, Safari, Edge) support it, but some legacy browsers may not recognize the header. The old Feature-Policy header name is still supported in some contexts for backward compatibility.

A practical rollout strategy involves sending both headers during a transition period:

Feature-Policy: geolocation=(), camera=()
Permissions-Policy: geolocation=(), camera=()

This ensures broader compatibility while supporting modern browsers with the newer header name. As browser support matures, you can deprecate the Feature-Policy header in favor of Permissions-Policy.

It's important to understand the relationship between Permissions-Policy and browser permissions. When a user grants permission to access a capability (by clicking "Allow" when a site requests camera access), that permission is separate from Permissions-Policy.

Permissions-Policy acts at the capabilities level: it controls whether an API is available at all. User permissions act at the browser level: even if an API is available due to Permissions-Policy, the browser still prompts the user before granting access. Both layers work together to create comprehensive permission management.

A user could deny camera access through the browser's permission dialog, even if your Permissions-Policy allows it. Conversely, if your Permissions-Policy denies camera access, the user will never see a permission prompt because the browser knows the capability isn't available on that page.

Testing and Validation of Permissions-Policy

Testing Permissions-Policy involves verifying that restricted capabilities actually fail when scripts attempt to use them. Browser developer tools show whether permissions are granted or denied. You can test by attempting API calls that should be blocked and confirming they fail gracefully.

More sophisticated testing involves security scanning tools that analyze your Permissions-Policy configuration and provide recommendations. Some security headers analysis tools can review your Permissions-Policy and identify capabilities you might have forgotten to restrict.

Relationship to Content Security Policy

While Permissions-Policy controls which browser APIs are available, Content Security Policy (CSP) controls where scripts can be loaded from and what they can do. These headers work together:

  • CSP prevents unsafe inline scripts and scripts from untrusted origins
  • Permissions-Policy restricts which APIs those scripts can access even if they execute

For comprehensive security, implement both headers. CSP provides the first line of defense by preventing malicious scripts from executing in the first place. Permissions-Policy provides the second line of defense by restricting what those scripts can do if they somehow execute.

Best Practices for Permissions-Policy Implementation

Start with a restrictive baseline: deny all potentially sensitive capabilities by default, then explicitly allow only those your application needs. This "deny by default, allow by exception" approach is more secure than the inverse.

Document why you need each permission. If you have camera=(self) in your header, document that your application uses peer-to-peer video calls that require camera access. This documentation helps you audit whether permissions are still needed as your application evolves.

Review permissions regularly. As your application evolves, some capabilities you previously enabled might no longer be needed. Regular audits ensure you're not carrying unnecessary permissions from legacy features.

Restrict third-party scripts aggressively. Explicitly specify which origins third-party services are allowed to access capabilities from. Avoid overly permissive allowlists like * unless absolutely necessary.

Use specific origins for trusted partners. Rather than allowing a broad domain, use the most specific origin possible. If a service is hosted at https://service.example.com, use that specific origin rather than allowing all subdomains.

Monitor permission usage. Log attempts to access restricted capabilities and alert on unexpected patterns. This helps identify when your site or third-party scripts are attempting to use capabilities they shouldn't need.

Future of Browser Permissions

As new browser capabilities are introduced (eye tracking, neural interfaces, AR/VR features), Permissions-Policy will evolve to encompass these new capabilities. The header provides a framework for managing whatever powerful APIs the web platform introduces in the future.

The trend in web security is toward more granular permission controls and explicit feature restrictions. Permissions-Policy represents this evolution—moving from an open model where all capabilities were available by default to a closed model where capabilities are explicitly granted only when needed.

Conclusion: Permissions-Policy as Part of Defense-in-Depth

Permissions-Policy is a critical security header that provides explicit control over browser capabilities. By restricting access to cameras, microphones, geolocation, payment APIs, and other sensitive features, you reduce your attack surface and protect users even if malicious code manages to execute on your site.

Implementing Permissions-Policy as part of a comprehensive security strategy—alongside Content Security Policy, HTTPS, secure dependency management, and other best practices—creates a defense-in-depth architecture where no single vulnerability completely compromises security. The header's ability to provide browser-level restrictions on sensitive APIs makes it an essential component of modern web application security.

Frequently Asked Questions

What is the Permissions-Policy header?

Permissions-Policy is an HTTP response header that lets a website declare which powerful browser features and APIs — such as camera, microphone, geolocation, and payment — are allowed to run on the page and inside its iframes. It works as an allowlist: any feature you do not explicitly enable is denied, which shrinks the attack surface available to malicious or compromised scripts.

Is Permissions-Policy the same as Feature-Policy?

Yes, functionally. Permissions-Policy is the renamed and restructured successor to the older Feature-Policy header. The concept is identical, but the syntax changed: Feature-Policy used semicolons and quoted keywords (geolocation 'self'), while Permissions-Policy uses a comma-separated structured format with parentheses (geolocation=(self)).

What does geolocation=() mean in a Permissions-Policy header?

Empty parentheses mean the feature is disabled everywhere — even for your own origin and any nested iframes. So geolocation=() blocks all location access on the page. Use self inside the parentheses (geolocation=(self)) to allow only your own origin, or list specific HTTPS origins to allow named third parties.

How do I disable all sensitive browser features by default?

Send a restrictive baseline that closes the features you do not use, for example: Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), bluetooth=(). Then add back only what your application genuinely needs, using self or a specific trusted origin.

Does Permissions-Policy replace asking the user for permission?

No. The two layers are independent. Permissions-Policy controls whether an API is available on the page at all; the browser permission prompt controls whether the user consents to use it. If Permissions-Policy denies a feature, the user is never even prompted. If it allows a feature, the browser still asks the user before granting access.

Do I still need to send the Feature-Policy header?

Almost never in 2026. All current major browsers support Permissions-Policy, so Feature-Policy is only useful if you must support very old browser versions. If you do send both during a transition, keep the two policies equivalent, then drop Feature-Policy once your analytics show no meaningful traffic from browsers that require it.

How is Permissions-Policy different from Content-Security-Policy?

They protect different things. Content-Security-Policy (CSP) controls where scripts, styles, and other resources may load from and whether inline code can run. Permissions-Policy controls which device and browser APIs any running script may reach. CSP tries to stop malicious code from executing; Permissions-Policy limits the damage if code executes anyway. Use both together for defense in depth.

Does Permissions-Policy control features inside iframes?

Yes. A page's Permissions-Policy applies to the document and to every nested iframe. An embedded frame cannot use a feature unless the parent page's policy allows it for that origin, and the frame can further tighten (but not widen) the policy using the iframe allow attribute. This makes Permissions-Policy a key control for third-party embeds.

How do I test my Permissions-Policy configuration?

Use browser DevTools (the Application or Issues panel reports blocked features) and a security-headers scanner that parses your header and flags missing restrictions. Try calling a blocked API in the console — a properly configured policy makes the call reject or throw rather than prompting the user.

web-securityheaderspermissions-policybrowser-securityapi-security