What Is the Permissions-Policy Header Used For?
Learn how the Permissions-Policy header restricts camera, microphone, and geolocation access for pages and iframes.
Expected Interview Answer
The Permissions-Policy header lets a site explicitly enable or disable powerful browser features — such as the camera, microphone, geolocation, or autoplay — for its own page and for any embedded iframes, so that neither a compromised script nor an untrusted third-party frame can invoke sensitive device or browser capabilities the site never intended to allow.
Modern browsers expose increasingly powerful APIs (camera, microphone, geolocation, fullscreen, payment, USB access), and by default many of these are available to a page and to any iframe it embeds unless explicitly restricted. Permissions-Policy lets a server declare, per feature, which origins are allowed to invoke it — for example camera=() disables camera access entirely for the page and all its frames, while camera=(self "https://trusted-widget.example.com") allows only the page’s own origin and one named trusted iframe. This is critical for pages that embed third-party content like ads, chat widgets, or payment iframes: without a restrictive policy, a compromised or malicious third-party script running inside an embedded iframe could attempt to request microphone or geolocation access using the embedding page’s permission context. The policy also lets a site proactively harden itself even for features it never uses, closing off capability an injected script could otherwise abuse if the site is compromised. It complements CSP (which controls what can load and execute) by controlling what browser features loaded code is allowed to call.
- Restricts sensitive browser APIs like camera, microphone, and geolocation per origin
- Protects against a compromised or malicious third-party iframe invoking device features
- Proactively disables unused capabilities so injected code cannot abuse them
- Complements CSP by governing browser feature access rather than resource loading
AI Mentor Explanation
Permissions-Policy is like a stadium deciding exactly which staff, and which visiting broadcast crews in the media box, are allowed to operate the on-field cameras and PA microphone. Home ground staff get full access, an accredited visiting crew might get camera-only access to one specific gantry, and everyone else gets none of it, no matter who wanders into the media box. Even if an intruder gets into the media box, they still cannot switch on equipment they were never granted permission to touch. That explicit, per-capability, per-party access grant is exactly what Permissions-Policy defines for browser features like the camera or microphone.
Step-by-Step Explanation
Step 1
Server declares feature-by-feature rules
The Permissions-Policy header lists browser features and which origins (self, none, or named origins) may invoke each one.
Step 2
Browser applies the policy to the page and its frames
The rule set governs both the top-level page and any iframes it embeds, including third-party content.
Step 3
A script or frame attempts to call a restricted API
When code calls something like navigator.mediaDevices.getUserMedia() or navigator.geolocation, the browser checks the active policy first.
Step 4
Browser blocks or allows based on the origin match
If the calling origin isn’t permitted for that feature, the API call is rejected or the permission prompt never appears at all.
What Interviewer Expects
- Explaining that Permissions-Policy governs browser features/APIs, not resource loading
- Understanding the self / origin-list / none syntax for scoping a feature
- Awareness of the third-party iframe threat model this header addresses
- Ability to distinguish Permissions-Policy from Content-Security-Policy
Common Mistakes
- Confusing Permissions-Policy with CSP, which controls resource loading and script execution instead
- Forgetting the header restricts embedded iframes’ feature access, not just the top-level page
- Not proactively disabling features the site never uses, missing a hardening opportunity
- Assuming the older Feature-Policy header name still works identically in modern browsers
Best Answer (HR Friendly)
“Permissions-Policy lets a website control which sensitive device features — like the camera, microphone, or location — it and anything embedded inside it are allowed to use. It’s a way of proactively locking down capabilities the site doesn’t need, so even a compromised ad or widget can’t secretly try to access your camera.”
Code Example
app.use((req, res, next) => {
res.set(
'Permissions-Policy',
[
'camera=(self)',
'microphone=()',
'geolocation=(self "https://maps.trusted-partner.example.com")',
'payment=()',
'usb=()',
].join(', ')
)
next()
})Follow-up Questions
- How does Permissions-Policy differ from the browser permission prompts users see?
- Why would you disable a feature via Permissions-Policy even if your site never uses it?
- How does Permissions-Policy interact with an iframe that also sets its own allow attribute?
- What replaced the older Feature-Policy header, and are they interchangeable?
MCQ Practice
1. What kind of capability does Permissions-Policy govern?
Permissions-Policy specifically restricts access to powerful browser features/APIs, not general resource loading.
2. What does camera=() mean in a Permissions-Policy header?
An empty allowlist () means no origin, including the page itself and any iframes, may use that feature.
3. Why is Permissions-Policy especially relevant for pages embedding third-party iframes?
Without an explicit policy, embedded third-party content can inherit access to powerful features; Permissions-Policy scopes that access per origin.
Flash Cards
What does Permissions-Policy control? — Which origins can invoke powerful browser features like camera, microphone, or geolocation.
What does an empty allowlist () mean for a feature? — The feature is disabled entirely for the page and all embedded frames.
Permissions-Policy vs CSP? — CSP governs what resources/scripts can load and execute; Permissions-Policy governs what browser APIs loaded code can call.
Why disable unused features proactively? — It closes off capability an injected or compromised script could otherwise abuse.