Permissions Policy, formerly known as Feature Policy, allows the developer to control the browser features available to a page, its iframes, and subresources, by declaring a set of policies for the browser to enforce. These policies are applied to origins provided in a response header origin list. The origin list can contain same-origins and/or cross-origins, and it allows the developer to control first-party and third-party access to browser features.
The user has the final decision to allow access to more powerful features, and needs to provide explicit permission by accepting a prompt.
Permissions Policy allows the top-level site to define what it and its third parties intend to use, and removes the burden from the user of determining whether the feature access request is legitimate or not. For example, by using Permissions Policy to block the geolocation feature for all third parties, the developer can be certain that no third party will gain access to the user's geolocation.
Permissions Policy was previously known as Feature Policy. The key concepts remain the same, but there are some important changes along with the name.
Structured Fields provide a set of common data structures to standardize parsing and serialization of HTTP header field values. Learn more about Structured Fields from Fastly's blog post, "Improving HTTP with structured header fields".
geolocation 'self' https://example.com; camera 'none'
Before with Feature Policy.
geolocation=(self "https://example.com"), camera=()
Now with Permissions Policy.
allow
attributeWith Feature Policy, you could add the feature to a cross-origin frame by either adding the origin to the header origin list or adding an allow
attribute to the iframe tag. With Permissions Policy, if you add a cross-origin frame to the origin list, the iframe tag for that origin must include the allow
attribute. If the response does not contain a Permissions Policy header, the origin list is considered to have the default value of *
. Adding the allow
attribute to the iframe allows access to the feature.
Therefore, we recommend developers explicitly set the Permissions Policy header in the response, so that cross-origin iframes which aren't listed in the origin list are blocked from accessing this feature, even if allow
is present.
Feature Policy can still be used after Chrome 88, but it acts as an alias for Permissions Policy. Other than the syntax, there is no difference in logic. If both Permissions Policy and Feature Policy headers are used together, the Permissions-Policy
header will have higher priority, and will overwrite the value provided by the Feature-Policy
header.
Before we dive deep, let's take a quick look at a common scenario where you are the owner of a website and you want to control how your site and third-party code use browser features.
https://your-site.example
.https://your-site.example
).https://trusted-site.example
that you trust.https://ad.example
.In this case, use the following header:
Permissions-Policy: geolocation=(self "https://trusted-site.example")
And explicitly set the allow
attribute to the iframe tag for the trusted site:
<iframe src="https://trusted-site.example" allow="geolocation">
In this example, the header origin list lets only your site (self
) and trusted-site.example
to use the geolocation feature. ad.example
is not allowed to use geolocation.
your-site.example
is allowed to use the geolocation feature with the user's consent.your-site.example
) is allowed to use the feature without the usage of the allow
attribute.subdomain.your-site-example
) that was not added to the origin list, and has the allow attribute set on the iframe tag, is blocked from using the feature. Different subdomains are considered same-site but cross-origin.trusted-site.example
) that was added to the origin list and has the allow
attribute set on the iframe tag is allowed to use the feature.trusted-site.example
) added to the origin list, without the allow
attribute, is blocked from using the feature.ad.example
) which wasn't added to the origin list is blocked from using the feature, even if the allow
attribute is included in the iframe tag.Permissions-Policy
HTTP response headerPermissions-Policy: <feature>=(<token>|<origin(s)>)
Use a Permissions-Policy
header in the response from the server to set the allowed origins for a feature. The header value can take a combination of tokens and strings of origins. The available tokens are *
for all origins and self
for same-origin.
If your header is for multiple features, separate the features with a comma. If you list multiple origins, separate each origin in the origin list with a space. For headers which list an origin that's a cross-origin request, the iframe tag must include the allow
attribute.
Here are some example key-value pairs:
[FEATURE]=*
geolocation=*
[FEATURE]=(self)
geolocation=(self)
[FEATURE]=(self [ORIGIN(s)])
geolocation=(self "https://a.example" "https://b.example")
self
is a shorthand for https://your-site.example
[FEATURE]=([ORIGIN(s)])
geolocation=("https://your-site.example" "https://a.example" "https://b.example")
self
token.[FEATURE]=()
geolocation=()
Different subdomains, such as https://your-site.example
and https://subdomain.your-site.example
, are considered same-site but cross-origin. Therefore, adding a subdomain in the origin list does not allow access to another subdomain of the same site. Every embedded subdomain that wants to use the feature must be added separately to the origin list. For example, if access to the user's browsing topics is allowed to the same-origin only with the header Permissions-Policy: browsing-topics=(self)
, an iframe from a different subdomain of the same site, https://subdomain.your-site.example
, won't have access to the topics.
Different paths, such as https://your-site.example
and https://your-site.example/embed
, are considered same-origin, and different paths don't have to be listed in the origin list.
allow
attributeFor cross-origin usage, an iframe needs the allow
attribute in the tag to gain access to the feature.
Syntax: <iframe src="[ORIGIN]" allow="[FEATURE] <'src' | [ORIGIN(s)]"></iframe>
For example:
<iframe src="https://trusted-site.example" allow="geolocation">
By default, if an iframe navigates to another origin, the policy is not applied to the origin that the iframe navigates to. By listing the origin that the iframe navigates to in the allow
attribute, the Permissions Policy that was applied to the original iframe will be applied to the origin the iframe navigates to.
<iframe src="https://trusted-site.example" allow="geolocation https://trusted-site.example https://trusted-navigated-site.example">
You can see it in action by visiting the iframe navigation demo.
The examples of the following setups can be found in the demo.
Permissions-Policy: geolocation=*
<iframe src="https://trusted-site.example" allow="geolocation"> <iframe src="https://ad.example" allow="geolocation">
When the origin list is set to the *
token, the feature is allowed for all origins present on the page, including itself and all iframes. In this example, all code served from https://your-site.example
and the codes served from https://trusted-site.example
iframe and https://ad.example
have access to the geolocation feature in the user's browser. Remember that the allow attribute must also be set on the iframe itself along with adding the origin to the header origin list.
This setup can be seen in the demo.
Permissions-Policy: geolocation=(self)
Using the self
token allows geolocation usage to the same-origin only. Cross-origins won't have access to the feature. In this example, only https://trusted-site.example
(self
) will have access to geolocation. Utilize this syntax if you want the feature only for your page and no one else.
This setup can be seen in the demo.
Permissions-Policy: geolocation=(self "https://trusted-site.example")
This syntax allows the usage of geolocation to both self (https://your-site.example
) and https://trusted-site.example
. Remember to explicitly add the allow attribute to the iframe tag. If there is another iframe with <iframe src="https://ad.example" allow="geolocation">
, then https://ad.example
won't have access to the geolocation feature. Only the original page and https://trusted-site.example
that is listed in the origin list along with having the allow attribute in the iframe tag will have access to the user's feature.
This setup can be seen in the demo.
Permissions-Policy: geolocation=()
With an empty origin list, the feature is blocked for all origins. This setup can be seen in the demo.
The existing JavaScript API of Feature Policy is found as an object on either the document or the element (document.featurePolicy or element.featurePolicy
). The JavaScript API for Permissions Policy has not been implemented yet.
The Feature Policy API can be used for policies set by Permissions Policy, with some limitations. There are remaining questions regarding a JavaScript API implementation, and a proposal has been made to move the logic into the Permissions API. Join the discussion if you have any thoughts.
true
if the feature is allowed for the default-origin usage.allowsFeature()
is called on an iframe element (iframeEl.featurePolicy.allowsFeature('geolocation')
), the returned value reflects if the allow attribute is set on the iframetrue
if the feature is allowed for the specified origin.document
, this method no longer tells you whether the feature is allowed for the specified origin like Feature Policy did. Now, this method tells you that it's possible for the feature to be allowed to that origin. You must conduct an additional check of whether the iframe has the allow
attribute set or not. The developer must conduct an additional check for the allow
attribute on the iframe element to determine if the feature is allowed for the third-party origin.element
objectYou can use element.allowsFeature(feature)
that takes the allow attribute into account unlike document.allowsFeature(feature, origin)
that does not.
constsomeIframeEl=document.getElementById('some-iframe')constisCameraFeatureAllowed=someIframeEl.featurePolicy.allowsFeature('camera')
Check out how Permissions Policy works in DevTools.
If you are using the Feature-Policy
header, you can implement the following steps to migrate to Permissions Policy.
Since the Feature Policy headers are only supported in Chromium-based browsers, and Permissions Policy headers are supported since Chrome 88, it is safe to update the existing headers with Permissions Policy.
Feature-Policy: autoplay *; geolocation 'self'; camera 'self' 'https://trusted-site.example'; fullscreen 'none';
Before with Feature Policy.
Permissions-Policy: autoplay=*, geolocation=(self), camera=(self "https://trusted-site.example"), fullscreen=()
Now with Permissions Policy.
document.allowsFeature(feature, origin)
usageIf you are using document.allowsFeature(feature, origin)
method to check allowed features for iframes, use allowsFeature(feature)
method attached on the iframe element, and not the containing document
. The method element.allowsFeature(feature)
accounts for the allow attribute while document.allowsFeature(feature, origin)
does not.
document
To continue using document
as the base node, then you must conduct an additional check for the allow
attribute on the iframe tag.
<iframe id="some-iframe" src="https://example.com" allow="camera"></iframe>
Permissions-Policy: camera=(self "https://example.com")
constisCameraPolicySet=document.featurePolicy.allowsFeature('camera','https://example.com')constsomeIframeEl=document.getElementById('some-iframe')consthasCameraAttributeValue=someIframeEl.hasAttribute('allow') &&someIframeEl.getAttribute('allow').includes('camera')constisCameraFeatureAllowed=isCameraPolicySet && hasCameraAttributeValue
Instead of updating the existing code using document
, it's recommended to call allowsFeature()
on the element
object like the previous example.
The Reporting API provides a reporting mechanism for web applications in a consistent manner, and Reporting API for Permissions Policy violations is available as an experimental feature.
If you would like to test the experimental feature, follow the walkthrough and enable the flag in chrome://flags/#enable-experimental-web-platform-features
. With the flag enabled, you can observe Permissions Policy violations in DevTools under the Application tab:
The following example shows how the Reporting API header may be constructed:
Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default" Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint; Document-Policy: document-write=?0; report-to=main-endpoint;
In the current implementation, you can receive policy violation reports from any violations occurring within that frame by configuring an endpoint named 'default' like the earlier example. Subframes will require their own reporting configuration.
For a deeper understanding of Permissions Policy, refer to the following resources:
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2022-04-20 UTC.