Locking down browser features on purpose
The Permissions-Policy header lets a page decide which powerful browser interfaces such as camera, microphone or location can be used at all, both for the page itself and for any embedded iframes. We cover the syntax, the difference from its predecessor Feature-Policy, and a practical configuration for a typical Magento shop.
Table of Contents
- 1. Why Controlling Browser Features Belongs in a Security Strategy
- 2. Syntax and Fundamentals of the Permissions-Policy Header
- 3. From Feature-Policy to Permissions-Policy: What Changed
- 4. Available Directives at a Glance
- 5. Restricting Iframes: How the Header Acts as a Ceiling
- 6. Difference from Content-Security-Policy: Two Complementary Headers
- 7. Practical Configuration for a Typical Magento Shop
- 8. Testing and Validation: Spotting Misconfigurations
- 9. Limitations of the Header and Browser Compatibility
- 10. Summary
- 11. FAQ
1. Why Controlling Browser Features Belongs in a Security Strategy
Modern browsers expose an ever growing set of powerful APIs to web pages: access to camera and microphone, location, vibration, motion sensors, or the Payment Request API. Every one of these interfaces can be useful for a legitimate purpose, a video call feature or a store locator relying on geolocation, but each also carries abuse potential if injected third party code, a compromised ad script, or a malicious embedded iframe reaches for it without the site owner ever knowing.
The Permissions-Policy header closes exactly that gap by defining, at the HTTP level, which browser features are even available to a document and all iframes embedded within it, regardless of whether some piece of JavaScript ever attempts to use them. Without the header, only the same-origin policy and the behavior of individual iframes decide which interfaces are reachable, which tends to be far more permissive than necessary.
2. Syntax and Fundamentals of the Permissions-Policy Header
The header follows the structured field syntax and lists, for every directive, an allowlist of origins permitted to use that feature. Two empty parentheses mean nobody may use the feature, not even the page's own origin. The keyword self permits only the page's own origin, while concrete domains in quotes unlock additional, trusted third parties, for example an embedded video widget.
Multiple directives are combined in a single header value, separated by commas. If a directive is missing entirely, the browser's specification default applies, and that default varies in how permissive it is depending on the feature. It is therefore worth naming every security-relevant feature explicitly rather than relying on browser defaults, which genuinely differ between Chrome, Firefox and Safari.
Permissions-Policy: camera=(), microphone=(), geolocation=(self),
payment=(), usb=(), xr-spatial-tracking=(), fullscreen=(self),
autoplay=(self), picture-in-picture=(self)
3. From Feature-Policy to Permissions-Policy: What Changed
Feature-Policy was the historical predecessor, introduced in browsers around 2018 with a syntactically different notation: origins were written in quotes and separated by spaces, for example camera 'self' https://example.com. Permissions-Policy replaces Feature-Policy, uses the more modern structured field syntax with parentheses, and is the authoritative standard in current browsers, while Feature-Policy has since been removed from many browsers or is treated as an alias at best.
Anyone who finds older documentation or code samples written in Feature-Policy syntax should not copy it unchanged, because modern browsers simply ignore a header whose syntax no longer matches the current specification. For maximum compatibility with older browser versions it can make sense to send both headers in parallel during a transition period, with the clear focus on Permissions-Policy since Feature-Policy is considered deprecated.
4. Available Directives at a Glance
The specification defines a growing list of directives, including camera, microphone, geolocation, payment, usb, midi, magnetometer, gyroscope, accelerometer, fullscreen, autoplay, encrypted-media, picture-in-picture and xr-spatial-tracking. Each directive controls exactly one browser feature, and not every API is equally supported across every browser, which makes checking current compatibility tables worthwhile before shipping a policy to production.
For most conventional web shops, the vast majority of these features are simply superfluous. A shop without its own video conferencing feature, without an in-browser payment integration through the Payment Request API, and without AR product previews needs neither camera nor usb nor xr-spatial-tracking, and should consistently disable these features to shrink the attack surface, even without a known concrete abuse case today.
5. Restricting Iframes: How the Header Acts as a Ceiling
The interplay with embedded iframes, from payment providers, ad networks or video platforms, matters most. The parent document's Permissions-Policy header acts as a ceiling: even when an iframe explicitly requests camera or microphone through its own allow attribute, access stays denied unless the parent page has granted that feature to the iframe's domain via the header.
This dual control layer, a header at the document level plus an allow attribute at the iframe level, prevents an embedded third party script from unilaterally gaining access to sensitive interfaces, even if it tries to manipulate its own iframe tag accordingly. Site owners should therefore review, for every embedded third party iframe, exactly which features it genuinely needs and unlock only those for that specific domain.
6. Difference from Content-Security-Policy: Two Complementary Headers
Permissions-Policy is frequently confused with Content-Security-Policy, even though the two serve different purposes. CSP controls which resources, scripts, stylesheets or images, may be loaded at all and from which sources, primarily protecting against cross-site scripting and data injection. Permissions-Policy operates one level higher and does not control resource loading but access to browser APIs after the code has already loaded and executed.
The two headers complement rather than overlap each other: a strict CSP prevents unauthorized code from ever reaching the page, while a strict Permissions-Policy additionally ensures that even legitimately loaded but compromised code cannot abuse sensitive hardware interfaces. A shop that only configures one of the two headers properly leaves an entire defense layer unused.
7. Practical Configuration for a Typical Magento Shop
For a typical Hyva-based Magento shop without its own video chat feature, without native payment hardware integration, and without AR features, a restrictive baseline configuration makes sense. Camera, microphone, usb, midi and xr-spatial-tracking get disabled entirely, geolocation is allowed at most for the page's own origin if a store locator genuinely needs it, and payment is only unlocked when an in-browser payment method through the Payment Request API is actually in use.
Fullscreen and picture-in-picture remain useful for the page's own origin, for embedded product videos for example, while autoplay likewise stays limited to self to stop embedded third party ads from playing automatically with sound. The header can be set centrally in the nginx vhost configuration or through a Magento response header extension, so it applies consistently to every response without touching individual templates.
8. Testing and Validation: Spotting Misconfigurations
After setting the header, a systematic check through the developer tools of any major browser pays off, where the actually delivered response headers can be inspected under the application security or network tab. Many browsers additionally log a console warning whenever a script tries to reach a feature blocked by policy, which provides valuable clues during testing about which features a page genuinely needs.
A common mistake is an overly restrictive configuration that breaks legitimate functionality, for example when a payment provider's iframe suddenly can no longer use its own payment feature because the parent policy never granted it for that domain. A structured test pass through every critical user flow after each policy change prevents a well-intentioned security measure from disrupting actual business operations.
9. Limitations of the Header and Browser Compatibility
Permissions-Policy reliably protects against abuse of the covered browser APIs, but it does not replace other security measures. An attacker who has already gained access to user data through an unrelated vulnerability, a classic cross-site scripting flaw with no connection to hardware APIs, is not stopped by this header. The measure addresses one specific attack vector and has to remain part of a broader security strategy, not a substitute for one.
Browser support is also not fully uniform: while Chrome and Chromium-based browsers support most directives comprehensively, individual features in Firefox or Safari sometimes lag behind or get interpreted differently. A shop should therefore consult current compatibility tables regularly and configure the header so it causes no harm in browsers that do not support a given directive, since unknown directives are simply ignored per the specification.
| Directive | Purpose | Recommendation for a Magento Shop | Risk of an Overly Open Configuration |
|---|---|---|---|
| camera | Access to the device camera | Disable entirely: camera=() | Third party script can request camera access |
| microphone | Access to the microphone | Disable entirely: microphone=() | Unnoticed eavesdropping via compromised code |
| geolocation | Determining the user's location | self only, if a store locator exists | Location data leaked to embedded third parties |
| payment | Access to the Payment Request API | self only when actively used, otherwise disable | Manipulated payment dialogs via third party code |
| usb | Access to WebUSB devices | Disable entirely: usb=() | Unauthorized access to connected USB devices |
Mironsoft
Security audits, OWASP-compliant hardening, and secure architecture
Applications that actually hold up against a real attack attempt?
We review existing applications for classic OWASP vulnerabilities, insecure authentication, and missing input validation, then build an architecture that structurally reduces attack surface instead of just patching individual symptoms.
Security Audit
Systematically checking OWASP Top 10, auth flows, and input validation for vulnerabilities.
Secure Architecture
Building rate limiting, encryption, and access controls correctly from the ground up.
Incident Readiness
Establishing logging, monitoring, and response processes for when things go wrong.
10. Summary
Permissions-Policy Header: The Essentials at a Glance
Core Idea
The header defines which browser APIs a page and its iframes can even use.
Predecessor
Feature-Policy used a different syntax and is now considered deprecated.
Effect on Iframes
The header acts as a ceiling above any single iframe's allow attribute.
Magento Practice
Disable camera, microphone, usb and xr tracking entirely in most shops.