Permissions Policy Limits Powerful Browser Features
A web page can contain code from several trust domains while still sharing access to browser capabilities. First-party scripts, third-party widgets, and nested frames may all execute inside one application surface. Browser permission prompts remain important, but an application can narrow the set of documents that are eligible to request or use selected features before a prompt becomes relevant.
Permissions Policy provides that boundary. A response header declares which origins may use controlled features in the document and its frame tree. The policy does not grant a user permission. It constrains feature availability within the browser.
Permissions-Policy: camera=(), microphone=(), geolocation=(self)Here, camera and microphone access are disabled by policy, while geolocation is limited to the document’s own origin.
The header defines an allowlist
Each policy directive names a feature and an allowlist. An empty list disables the feature. self identifies the document’s origin. Explicit origins can be listed when a deployment needs to delegate a feature to another origin.
Permissions-Policy: geolocation=(self "https://maps.example.net")The header is therefore most useful when it reflects an application’s actual capability map. A site with no camera workflow can disable camera access globally instead of leaving that capability available to every document that would otherwise qualify.
This is a reduction of exposed capability, not a replacement for application authorization or browser permission checks.
Frame boundaries matter
Embedded content is a common reason to set an explicit policy. A top-level document can restrict features inherited by descendants, and an iframe can carry an allow attribute that further controls delegated features for that frame.
<iframe
src="https://maps.example.net/widget"
allow="geolocation">
</iframe>Delegation is not simply an iframe request for extra authority. The effective result is constrained by the policy inherited from ancestors as well as the frame’s own declaration. A child frame cannot use an allow attribute to escape a stricter ancestor policy.
That property lets the embedding application retain control over browser capabilities exposed to third-party content.
Policy denial is separate from user consent
Permissions Policy and user permission operate at different layers. A feature blocked by policy is unavailable to the document even if the user previously granted the relevant permission. Conversely, allowing a feature through policy does not automatically satisfy a permission requirement imposed by the browser.
A useful model is:
policy permits feature
|
v
browser permission or other feature rules
|
v
feature may become usableThis distinction prevents an unsafe interpretation of the header as a permission-grant mechanism. It is a capability ceiling.
Start from features the application does not need
A practical policy can begin by disabling sensitive capabilities that have no valid use in the application. That approach creates a narrow baseline without requiring speculative origin lists.
Permissions-Policy: camera=(), microphone=(), geolocation=(), usb=()Feature names and browser support vary, so production policy should be checked against the features actually implemented by the target browsers. A directive that is unsupported by a user agent cannot provide the expected enforcement there.
When a feature is required, delegation should match the smallest origin and frame scope that supports the workflow.
Third-party widgets need explicit capability review
An embedded service may need one browser feature while having no operational reason to receive others. Treating all third-party frames alike expands capability exposure and makes future integration changes harder to audit.
A capability inventory can record the relationship directly:
frame origin required feature
maps.example.net geolocation
video.example.net camera, microphone
analytics.example.net noneThe resulting policy can then be reviewed beside CSP, iframe sandboxing, and application authorization. These controls cover different boundaries. CSP primarily constrains content loading and execution sources; iframe sandboxing changes a frame’s available behaviors; Permissions Policy governs designated browser features.
Reports and tests should verify the effective boundary
A header can be syntactically present while failing to represent the intended frame hierarchy. Integration tests should exercise the real embedding path and confirm that permitted frames can use required capabilities while non-permitted frames cannot.
Browser developer tooling can also expose policy-related diagnostics. Automated tests remain valuable because delegation can change when a widget moves to another origin or gains an additional nesting layer.
Policy review should include redirects and generated iframe URLs. An origin allowlist only matches the origins covered by its syntax; deployment changes can therefore alter the effective capability boundary without changing application code that calls the browser API.
Capability minimization belongs at the document boundary
Permissions Policy is strongest as a least-capability control. The top-level application states which browser features belong in its document tree, then delegates only the portions required by specific embedded content.
That boundary does not make third-party code trusted, and it does not replace consent, authorization, CSP, or sandboxing. It removes browser capabilities from documents that have no operational need for them, shrinking the authority available when embedded code behaves unexpectedly or an integration changes.
References
- MDN, Permissions-Policy header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Permissions-Policy
- W3C, Permissions Policy: https://www.w3.org/TR/permissions-policy-1/