Feature Policy Legacy Notes
Feature-Policy renamed to Permissions-Policy: migration notes, old header syntax, and what still matters.
- browser
- feature-policy
- permissions-policy
- headers
- security
Feature-Policy was the earlier name and header for controlling browser features (camera, geolocation, frexpensive APIs) per document and iframe. It has been superseded by Permissions-Policy. You still see the old name in blog posts, Stack Overflow, and legacy code — this page is the migration map.
Docs: MDN Permissions-Policy, Feature-Policy deprecation notes, Permissions Policy explainer.
Rename at a glance
| Era | Header | Example idea |
|---|---|---|
| Legacy | Feature-Policy |
geolocation 'none' |
| Current | Permissions-Policy |
geolocation=() |
Syntax changed — you cannot only rename the header string.
Old Feature-Policy style
Feature-Policy: geolocation 'none'; microphone 'none'; camera 'self'
Modern Permissions-Policy style
Permissions-Policy: geolocation=(), microphone=(), camera=(self)
| Allowlist token (modern) | Meaning |
|---|---|
* |
All origins (where allowed) |
() empty |
Disabled for everyone including self |
(self) |
Same origin |
(self "https://partner.example") |
Self + listed origins |
iframe allow attribute
Features can also be delegated on iframes:
<iframe
src="https://widget.example/embed"
allow="payment *; geolocation 'none'"
></iframe>
Combine with sandbox for stronger isolation — Sandboxing iframes. Header policy on the embedder + allow on the frame interact; the effective policy is the intersection of restrictions.
Why frontend cares
- Third-party embeds shouldn’t get camera/mic by default.
- Defense in depth if an XSS fires — disable powerful APIs the page doesn’t need.
- Breakages after enabling strict policy look like “API always denies” — check policy before blaming permissions prompts.
navigator.geolocation.getCurrentPosition(console.log, console.error);
// error may be policy, not user denial
Migration checklist
- Search code and CDN configs for
Feature-Policy. - Convert directives to Permissions-Policy syntax.
- Test iframes and payment widgets.
- Prefer shipping only Permissions-Policy on greenfield.
- Keep a short internal doc of allowed features per product surface.
Full directive list and product guidance: Permissions Policy.
Interview out-loud
“Feature-Policy was renamed to Permissions-Policy with a new allowlist syntax. Empty list disables a feature; self and listed origins re-enable. I use it to lock down camera, mic, geolocation, and other powerful APIs, especially with third-party iframes.”
Search-and-replace traps
Replacing the header name without converting syntax silently fails open or closed depending on browser parse quirks. Always retest camera/geolocation pages after migration. Keep a single source of policy in edge config (not copy-pasted Feature-Policy in five services).
Related
Further depth
Teams often under-invest in this topic until an incident or CWV regression. Schedule a one-hour drill: reproduce the failure mode in DevTools, list the top three mitigations for your stack, and file tickets with owners. Revisit after the next major feature that touches networking, rendering, auth, or third parties — those are the moments regressions land. Keep primary documentation links in the runbook so on-call is not searching chat history at 2am.
Concrete artifacts to leave behind: a short architecture note, a CI assertion or header snapshot, and a dashboard panel (lab or field) that would have caught the last bug. Teaching the rest of the team the mental model matters as much as the one-line fix.
Further reading
Related guides
- Permissions PolicyLock down camera, geolocation, payment, and other powerful features with Permissions-Policy headers and iframe allow.
- Content-Type and MIME SniffingWhy Content-Type matters, how MIME sniffing works, X-Content-Type-Options: nosniff, and XSS-ish pitfalls.
- CORS Explained for FrontendWhy the browser blocks cross-origin responses, what Access-Control-* headers mean, preflight, credentials, and how to fix real frontend errors.
- Cross-Origin Embedder PolicyCOEP require-corp / credentialless: cross-origin isolation, SharedArrayBuffer, and embedding requirements.
- Cross-Origin Opener PolicyCOOP same-origin and same-origin-allow-popups: sever window.opener, process isolation, and OAuth popups.