1. Introduction
The web-platform provides an ever-expanding set of features and APIs, offering richer functionality, better developer ergonomics, and improved performance. However, a missing piece is the ability for the developer to selectively enable, disable, or modify the behavior of some of these browser features and APIs within their application:
- The developer may want to selectively disable access to certain browser features and APIs to "lock down" their application, as a security or performance precaution, to prevent own and third-party content executing within their application from introducing unwanted or unexpected behaviors within their application.
- The developer may want to selectively enable access to certain browser features and APIs which may be disabled by default - e.g. some features may be disabled by default in embedded context unless explicitly enabled; some features may be subject to other policy requirements.
- The developer may want to use the policy to assert a promise to a client or an embedder about the use—or lack of thereof—of certain features and APIs. For example, to enable certain types of "fast path" optimizations in the browser, or to assert a promise about conformance with some requirements set by other embedders - e.g. various social networks, search engines, and so on.
This specification defines a feature policy mechanism that addresses the above use cases.
2. Examples
SecureCorp Inc. wants to disable use of Vibration and Geolocation APIs within their application. It can do so by delivering the following HTTP response header to define a feature policy:
Feature-Policy: {"vibrate": [], "geolocation": []}
By specifying an empty list of origins, the specified features will be disabled for all browsing contexts, regardless of their origin.
SecureCorp Inc. wants to disable use of Geolocation API within all
browsing contexts except for its own origin and those whose origin is
"https://example.com
". It can do so by delivering the
following HTTP response header to define a feature policy:
Feature-Policy: {"geolocation": ["self", "https://example.com"]}
The allowlist is a list of one or more origins, which can include
the application’s origin, optionally with the keyword "self
",
and any third-party origin.
SecureCorp Inc. is hosting an application on
"https://example.com
" and wants to disable camera and
microphone input on its own origin but enable it for a whitelisted embedee
("https://other.com
"). It can do so by delivering the
following HTTP response header to define a feature policy:
Feature-Policy: {"camera": ["https://other.com"], "microphone": ["https://other.com"]}
Some features are disabled by default in embedded contexts. The enable policy allows the application to selectively enable such features for whitelisted origins.
FastCorp Inc. wants to disable geolocation for all cross-origin child frames, except for a specific iframe. It can do so by delivering the following HTTP response header to define a feature policy:
Feature-Policy: {"geolocation": ["self"]}
and including an "allow
" attribute on the iframe
element:
<iframe src="https://other.com/map" allow="geolocation"></iframe>
Iframe attributes can selectively enable features in certain frames, and not in others, even if those contain documents from the same origin.
3. Other and related mechanisms
[HTML5] defines a sandbox
attribute for iframe
elements
that allows developers to reduce the risk of including potentially untrusted
content by imposing restrictions on content’s abilities - e.g. prevent it
from submitting forms, running scripts and plugins, and more. The sandbox directive defined by [CSP2] extends this capability to any
resource, framed or not, to ask for the same set of restrictions - e.g. via an
HTTP response header (Content-Security-Policy: sandbox
). These
mechanisms enable the developer to:
- Set and customize a sandbox policy on any resource via CSP.
- Set and customize individual sandbox policies on each
iframe
element within their application.
However, there are several limitations to the above mechanism: the developer cannot automatically apply a policy across all contexts, which makes it hard or impossible to enforce consistently in some cases (e.g. due to third-party content injecting frames, which the developer does not control); there is no mechanism to selectively enable features that may be off by default; the sandbox mechanism uses a whietlist approach which is impossible to extend without compatibility risk.
Feature Policy is intended to be used in combination with the sandbox mechanism (i.e. it does not duplicate feature controls already covered by sandbox), and provides an extensible mechanism that addresses the above limitations.
4. Framework
4.1. Features
A feature controlled by this framework is an API or behaviour which can be enabled or disabled in a document or web worker by referring to it in a feature policy.
Features have a feature name keyword, which is a token used in policy directives, and a default allowlist, which defines whether the feature is available to top-level documents, and how access to that feature is inherited by cross-origin frames.
A user agent has a set of supported features, which is the set of features which it allows to be controlled through policies. User agents are not required to support every feature.
Features themselves are not themselves part of this framework. A non-normative list of currently-defined features is included as an appendix to this specification.
4.2. Policies
A Document
or WorkerGlobalScope
has a feature policy,
which consists of:
- A set of inherited policies.
- A declared policy.
4.3. Inherited policies
Each document in a frame tree inherits a set of policies from its parent frame, or in the case of the top-level document, from the defined defaults for each feature. This inherited policy set determines the initial state (enabled or disabled) of each feature, and whether it can be controlled by a declared policy in the document.
In a Document
in a top-level browsing context, or in a WorkerGlobalScope
, the inherited feature set is based on defined
defaults for each feature.
In a Document
in a nested browsing context, the inherited feature
set is based on the parent document’s feature policy, as well as any allow attributes defined on the
browsing context container.
An inherited policy for a feature is a boolean associated with that feature in a Document or WorkerGlobalScope. It can take the value Enabled or Disabled.
An inherited policy set for a Document
or WorkerGlobalScope
is the set of inherited policies for each feature available in that scope.
4.4. Declared policies
A declared policy is a set of policy directives, which may be the empty set.
The declared policy is represented in HTTP headers and HTML attributes as a JSON string.
A Document
or WorkerGlobalScope
is considered feature-policy-aware if it has a declared policy delivered
via a Feature-Policy HTTP header.
A Document
or WorkerGlobalScope
is which is not feature-policy-aware is considered feature-policy-oblivious.
4.5. Header policies
A header policy is a declared policy delivered via an HTTP header with the document, or in an HTML meta element in the document’s HEAD. These form the document’s feature policy’s declared policy.
4.6. Container policies
In addition to the header policy, each frame has a container policy, which is a policy directive, which may be empty. The container policy can set by attributes on the browsing context container.
The container policy for a frame influences the inherited policy of any document loaded into that frame. (See §8.8 Define an inherited policy for feature)
iframe
"allowfullscreen
",
"allowpaymentrequest
",
and "allow
"
attributes. Future revisions to this spec may introduce a mechanism to
explicitly declare the full container policy. 4.7. Policy directives
A policy directive is a dictionary, mapping feature names to corresponding allowlists of origins.
The following sections define the set of known feature names. Future versions of this document may define additional such names, as user agents ignore policy directives with unrecognized names when parsing the policy.
4.8. Allowlists
A feature policy allowlist is a set of origins. An allowlist may be empty, in which case it does not match any origin, or it may contain a list of origins, or it may match every origin. When defining an allowlist in a policy, the special origin "self" may be used, which refers to the origin of document which the policy is associated with.
An allowlist matches an origin o if it matches every origin, or if it contains an origin which is same origin-domain with o.
4.9. Default Allowlists
Every feature controlled by policy has a default allowlist, which is an allowlist. The default allowlist controls the origins which are allowed to access the feature when used in a top-level document with no declared policy, and also determines whether access to a feature is automatically delegated to child documents.
Features are currently defined to have one of these three default allowlists:
- ["
*
"] - The feature is allowed at the top level by default, and when allowed, is allowed by default to documents in child frames.
- ["
self
"] - The feature is allowed at the top level by default, and when allowed, is allowed by default to same-origin domain documents in child frames, but is disallowed by default in cross-origin documents in child frames.
- []
- The feature is disallowed at the top level by default, and is also disallowed by default to documents in child frames.
5. Feature Policy Serialization
5.1. JSON serialization
Declared Policies are represented in HTTP headers and in HTML attributes as JSON text [RFC7159].
origin
is the ASCII serialization of an origin.
feature-name
is a JSON string.
self
" may be used as an origin in an allowlist.
When it is used in this way, it will refer to the origin of the document
which contains the feature policy. 6. Delivery
6.1. Feature-Policy HTTP Header Field
The Feature-Policy HTTP header field can be used in the response (server to client) to communicate the feature policy that should be enforced by the client.
The header’s value is the §5.1 JSON serialization of the elements of the declared policy:
FeaturePolicy = 1#json-field-value ; See Section 2 of [[HTTP-JFV]], and Section 2 of [[RFC7159]]
When the user agent receives a Feature-Policy
header field,
it MUST process and enforce the serialized policy as described in §7.1 Integration with HTML.
6.2. The meta
element
A Document
may deliver a policy via one or more HTML meta
elements whose http-equiv
attributes are an ASCII case-insensitive match for the string
"Feature-Policy
". For example:
<meta http-equiv="Feature-Policy" content='{"webrtc": [], "geolocation": ["https://example.com"]}'>
The meta
policy is processed as defined in §7.1.1 Process meta policy and modifications to the content
attribute of a meta
element after the
element has been parsed MUST be ignored.
To ensure that the policy can be applied before any scripts are able to
execute within the Document
's browsing context, the following
restrictions apply to meta
policy:
6.3. The allow
attribute of the iframe
element
partial interface HTMLIFrameElement { [CEReactions, SameObject, PutForwards=value] readonly attribute DOMTokenList allow; };
iframe
elements have an "allow
" attribute, which
contains an unordered set of unique space-separated tokens that are ASCII
case-insensitive. The allowed values are names of features. Unrecognized
values must be ignored.
When not empty, the "allow
" attribute will result in adding
an allowlist for each recognized feature to the frame’s container
policy, when it is contructed.
The allowlist will contain a single origin, which is the origin
of URL in the iframe’s src
attribute.
6.4. Additional attributes to support legacy features
Some features controlled by Feature Policy have existing iframe attributes defined. This specification redefines these attributes to act as declared policies for the iframe element.
6.4.1. allowfullscreen
The "allowfullscreen
" iframe attribute controls access to requestFullscreen()
.
If the iframe element has an "allow
" attribute whose
value contains the token "fullscreen
", then the
"allowfullscreen
attribute should have no effect.
Otherwise, the presence of an "allowfullscreen" attribute on an iframe
will result in adding an allowlist of ["*
"] for the
"fullscreen" feature to the frame’s container policy, when it is
constructed.
<iframe
allow="fullscreen">
, and is for compatibility with existing
uses of allowfullscreen
. If allow="fullscreen"
and allowfullscreen
are
both present on an iframe element, then the more restrictive allowlist
of allow="fullscreen"
will be used. 6.4.2. allowpaymentrequest
The "allowpaymentrequest
" iframe attribute controls
access to Payment interface.
If the iframe element has an "allow
" attribute whose
value contains the token "payment
", then the
"allowpaymentrequest
attribute should have no effect.
Otherwise, the presence of an "allowpaymentrequest" attribute on an
iframe will result in adding an allowlist of ["*
"] for
the "payment" feature to the frame’s container policy, when it is
constructed.
<iframe
allow="payment">
, and is for compatibility with existing uses
of allowpaymentrequest
. If allow="payment"
and allowpaymentrequest
are both present on an iframe
element, then the more restrictive allowlist of allow="payment"
will be used. 7. Integrations
This document defines a set of algorithms which other specifications will use in order to implement the restrictions which Feature Policy defines. The integrations are outlined here for clarity, but those external documents are the normative references which ought to be consulted for detailed information.
7.1. Integration with HTML
-
Document
andWorkerGlobalScope
objects have a Feature Policy, which is populated via the §8.7 Initialize global’s Feature Policy from response algorithm that is called during the "Initialising a newDocument
object" and "Run a Worker" algorithms. -
Replace the existing step 12 of "Initialising a new
Document
object" with the following step:- Initialize the feature policy for the
Document
- Initialize the feature policy for the
- A feature policy is enforced for
a
Document
orWorkerGlobalScope
by setting it as theDocument
orWorkerGlobalScope
's Feature Policy. -
The "allowed to use" algorithm calls into §8.9 Is feature enabled in global for origin?, as follows:
-
Replace the current steps #3 and #4 with the following step:
- If
Document
’s feature policy enables the feature indicated byallowattribute
for the origin ofDocument
, then return true.
- If
-
Replace the current steps #3 and #4 with the following step:
7.1.1. Process meta policy
meta
[pragma directives]. This pragma extends the declared feature policy for a Document
.
- If the [meta] element has no [content] attribute, or if that attribute’s value is the empty string, then abort these steps.
- If the [meta] element is not being inserted in into the
Document
's [head] element, or if is inserted after any [script] or [link] elements, then abort these steps. - Let document be the meta element’s node document
- Let value be the result of parsing the value of [meta] element’s [content] attribute with a [JSON parser].
- If parsing returns an error, or value is not a [JSON object], then abort these steps.
- Let directive be the result of running §8.3 Parse policy directive from value and origin on value and document’s [origin].
- Run §8.4 Merge directive with declared policy with directive and document’s feature policy’s declared policy
8. Algorithms
8.1. Process response policy
Given a response (response) and global object (global), this algorithm returns a declared feature policy.
- Abort these steps if the response’s header list does
not contain a header whose name is "
Feature-Policy
". - Let header be the concatenation of the values of all header fields in response’s header list whose name is
"
Feature-Policy
", separated by commas (according to [RFC7230, 3.2.2]). - Add a leading "[" U+005B character, and a trailing "]" U+005D character to header.
- Let feature policy be the result of executing §8.2 Parse header from value and origin on header and global’s origin.
- Return feature policy.
8.2. Parse header from value and origin
Given a string (value) and an origin (origin) this algorithm will return a declared feature policy.
- Let policy be an empty list.
- Let list be the result of parsing value with a JSON Parser. If value cannot be parsed, return policy.
- Note: If value can be parsed, list must be a valid JSON Array.
-
For each element in list:
- If element is not a JSON object, then continue.
- Let directive be the result of executing §8.3 Parse policy directive from value and origin on element and origin
- Run §8.4 Merge directive with declared policy on directive and policy.
- Return policy.
8.3. Parse policy directive from value and origin
Given a JSON object (value) and an origin (origin) this algorithm will return a policy directive.
- Let directive be a new dictionary, mapping features to allowlists.
-
For each key and associated targetlist in value:
- If key is not equal to the name of any recognized feature, then continue.
- Let feature be the feature named by key.
- If targetlist is not an array, then continue.
- Let allowlist be a new allowlist.
- If targetlist contains the string "
*
", set allowlist to match every origin. -
Otherwise, for each element in targetlist:
- If element is an ASCII case-insensitive match for
"
self
", let result be origin. - Otherwise, let result be the result of executing the URL parser on element.
-
If result is not failure:
- Let target be the origin of result.
- If target is not an opaque origin, append target to allowlist.
- If element is an ASCII case-insensitive match for
"
- Insert allowlist into directive as the value for the key feature.
- Return directive
8.4. Merge directive with declared policy
Given a policy direcive (directive) and a declared policy (policy), this algorithm will modify policy to account for the new directive.
-
For each feature and associated allowlist in directive:
- If policy does not contain an allowlist for feature, then add allowlist to policy as the allowlist for feature.
8.5. Process feature policy attributes
Given an element element, this algorithm returns a declared feature policy, which may be empty.
- Let policy be a new policy directive.
- Let valid-features be the result of running Parse allow attribute on the value of element’s
allow
attribute. -
For each feature in valid-features:
-
If policy does not contain an allowlist for feature:
- Construct a new declaration for feature, whose allowlist is origin.
- Add declaration to policy.
-
If policy does not contain an allowlist for feature:
-
If element is an
iframe
element:-
If element’s
allowfullscreen
attribute is specified, and policy does not contain an allowlist for fullscreen,- Construct a new declaration for fullscreen, whose allowlist matches all origins.
- Add declaration to policy.
-
If element’s
allowpaymentrequest
attribute is specified, and policy does not contain an allowlist for payment,- Construct a new declaration for payment, whose allowlist matches all origins.
- Add declaration to policy.
-
If element’s
- Return policy.
8.6. Parse allow attribute
Given a list, this algorithm returns a list of feature name keywords, which may be empty.
- Let valid-features be an empty list.
- If list is
null
or empty, return valid-features. -
For each item in list:
- Convert item to ASCII-lowercase.
-
If item matches a defined feature name which is
not present in valid-features,
- Append item to valid-features.
- Return valid-features.
8.7. Initialize global’s Feature Policy from response
Given a response (response) and a global object (global), this algorithm populates global’s Feature Policy
- Let inherited policies be a new ordered map.
- Let declared policies be a new ordered map.
-
For each feature supported,
- Let isInherited be the result of running §8.8 Define an inherited policy for feature on feature and global.
- Set inherited policies[feature] to isInherited.
- Let d be the result of executing §8.1 Process response policy on response and global.
-
For each directive in d:
- If inherited policies[ in inherited policies for directive’s feature is true, then append d to declared policies
- Let policy be a new feature policy, with inherited policy set inherited policies and declared policy set declared policies.
- Enforce the policy policy.
8.8. Define an inherited policy for feature
Given a string (feature) and a browsing context (context), this algorithm returns the inherited policy for that feature.
-
If context is a nested browsing context:
- Let parent be context’s parent browsing context’s active document.
- Let origin be parent’s origin
- Let container policy be the result of running §8.5 Process feature policy attributes on context’s browsing context container.
-
If feature is a key in container policy:
- If the allowlist for feature in container policy matches origin, and parent’s inherited policy for feature is Enabled, return Enabled.
- Otherwise return Disabled.
- Otherwise, if feature is allowed by parent’s feature policy for origin, return Enabled.
- Otherwise, return Disabled.
- Otherwise, return Enabled.
8.9. Is feature enabled in global for origin?
Given a string (feature) and a global object
(global), and an origin (origin), this algorithm
returns "Disabled
" if feature should be considered
disabled, and "Enabled
" otherwise.
- Let policy be global’s Feature Policy
- If policy’s inherited policy for feature is Disabled, return "
Disabled
". -
If feature is present in policy’s declared
policy:
- If the allowlist for feature in policy’s declared policy matches origin, then return "
Enabled
". - Otherwise return "
Disabled
".
- If the allowlist for feature in policy’s declared policy matches origin, then return "
- If feature’s default allowlist is
["*"]
, return "Enabled
". - If feature’s default allowlist is
["self"]
, and origin is same origin-domain with global’s active document’s origin, return "Enabled
". - Return "
Disabled
".
9. IANA Considerations
The permanent message header field registry should be updated with the following registration [RFC3864]:
- Header field name
- Feature-Policy
- Applicable protocol
- http
- Status
- standard
- Author/Change controller
- W3C
- Specification document
- Feature Policy API
10. Privacy and Security
Appendix A: Features
This appendix is a reference to currently-defined valid features, their feature name keywords, and their effect effect when applied via a directive as part of a feature policy. This reference is non-normative; the actual definitions are given in subsections below.
Feature name | Default allowlist | Brief description |
---|---|---|
camera | self
| Controls access to video input devices. |
eme | self
| Controls whether requestMediaKeySystemAccess() is allowed.
|
fullscreen | self
| Controls whether requestFullscreen() is allowed.
|
geolocation | self
| Controls access to Geolocation interface. |
microphone | self
| Controls access to audio input devices. |
midi | self
| Controls access to requestMIDIAccess() method.
|
payment | self
| Controls access to PaymentRequest interface. |
speaker | self
| Controls access to audio output devices. |
vibrate | self
| Controls access to vibrate() method.
|
Feature Definitions
camera
The camera feature controls access to video input devices requested through the NavigatorUserMedia interface ([MEDIACAPTURE-API]).
If disabled in a document, then calls to getUserMedia() MUST NOT grant access to video input devices in that document.
The feature name for camera is "camera
"
The default allowlist for camera is ["self"]
.
eme
The eme keyword controls whether encrypted media extensions [encrypted-media] are available.
If disabled in a document, the promise returned by requestMediaKeySystemAccess()
must reject with a NotSupportedError.
The feature name for eme is "eme
"
The default allowlist for eme is ["self"]
.
fullscreen
The fullscreen keyword controls whether the requestFullscreen()
method ([WHATWG-FULLSCREEN]) is allowed to
request fullscreen.
If disabled in any document, the document will not be allowed to use fullscreen. If enabled, the document will be allowed to use fullscreen.
The feature name for fullscreen is
"fullscreen
"
The default allowlist for fullscreen is ["self"]
.
geolocation
The geolocation keyword controls whether the current document is alowed to use the Geolocation interface ([GEOLOCATION-API]).
If disabled in any document, calls to both getCurrentPosition and watchPosition must result in the error callback being invoked with PERMISSION_DENIED.
The feature name for geolocation is
"geolocation
"
The default allowlist for geolocation is ["self"]
.
microphone
The microphone feature controls access to audio input devices requested through the NavigatorUserMedia interface ([MEDIACAPTURE-API]).
If disabled in a document, then calls to getUserMedia() MUST NOT grant access to audio input devices in that document.
The feature name for microphone is "microphone
"
The default allowlist for microphone is ["self"]
.
midi
The midi keyword controls whether the current document is
allowed to use the requestMIDIAccess()
method ([WEBMIDI]).
If disabled in a document, the promise returned by requestMIDIAccess must reject with a DOMException parameter.
The feature name for midi is "midi
"
The default allowlist for midi is ["self"]
.
payment
The payment feature controls whether the current document is allowed to use the PaymentRequest interface ([PAYMENT-REQUEST]).
If disabled in a document, then calls to the PaymentRequest constuctor MUST throw a SecurityError.
The feature name for payment is "payment
"
The default allowlist for payment is ["self"]
.
speaker
The speaker feature controls access to audio output devices requested through the NavigatorUserMedia interface ([audio-output]).
If disabled in a document, then calls to getUserMedia() MUST NOT grant access to audio output devices in that document.
The feature name for speaker is "speaker
"
The default allowlist for speaker is ["self"]
.
vibrate
The vibrate feature controls whether the vibrate()
method ([VIBRATION]) is allowed to cause device vibration.
If disabled in a document, then calls to the vibrate()
method
should silently do nothing. If enabled, the browser may allow the device
to vibrate.
The feature name for vibrate is "vibrate
"
The default allowlist for vibrate is ["self"]
.