Feature Policy

Draft Community Group Report,

This version:
https://wicg.github.io/feature-policy/
Issue Tracking:
GitHub
Inline In Spec
Editor:
(Google)

Abstract

This specification defines a mechanism that allows developers to selectively enable and disable use of various browser features and APIs.

Status of this document

This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

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:

  1. 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.
  2. 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.
  3. 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 'none'; geolocation 'none'

By specifying the "'none'"keyword for the origin list, 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 specific 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 policy allows the application to selectively enable such features for specified 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.

[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:

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 automatically disables all sandbox features, and requires the developer to opt back in to each of them, so it is impossible to extend the set of sandbox features without significant 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. Policy-controlled Features

A policy-controlled feature is an API or behaviour which can be enabled or disabled in a document by referring to it in a feature policy.

For brevity, policy-controlled features will often be referred to in this document simply as "Features". Unless otherwise indicated, the term "feature" refers to policy-controlled features. Other specifications, defining such features, should use the longer term to avoid any ambiguity.

Policy-controlled features are identified by tokens, which are character strings used in policy directives.

Each policy-controlled feature has a default allowlist, which defines whether that 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.

The policy-controlled features themselves are not themselves part of this framework. A non-normative list of currently-defined features is maintained as a companion document alongside this specification.

4.2. Policies

A Document has a feature policy, which consists of:

An empty feature policy has an inherited policy set which contains 'Enabled' for every policy-controlled feature available, and a declared policy which is an empty map.

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 policy-controlled 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, 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 declares a feature as Enabled or Disabled.

An inherited policy set for a Document is the set of inherited policies for each feature available in that scope.

4.4. Declared policies

A declared policy is an ordered map from features to allowlists.

A Document is considered feature-policy-aware if it has a declared policy which is not empty.

A Document which is not feature-policy-aware is considered feature-policy-oblivious.

4.5. Header policies

A header policy is a list of policy directives delivered via an HTTP header with the document. This forms 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.9 Define an inherited policy for feature)

Currently, the container policy cannot be set directly, but is indirectly set by 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 an ordered map, mapping policy-controlled features to corresponding allowlists of origins.

A policy directive is represented in HTTP headers and HTML attributes as its ASCII serialization.

4.8. Allowlists

A feature policy allowlist is conceptually a set of origins. An allowlist may be either:

The keywords 'self', 'src', and 'none' can appear in the text representation of allowlists in headers and attribute strings. These keywords are always interpreted in context during parsing, and only the origins which they refer to are stored in the allowlist. The keywords themselves are not part of the allowlist.

To determine whether an allowlist matches an origin origin, run these steps:

  1. If the allowlist is the special value *, then return true.
  2. Otherwise, for each item in the allowlist:
    1. If item is same origin-domain with origin, then return true.
  3. return false.

4.9. Default Allowlists

Every policy-controlled feature has a default 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 the feature is automatically delegated to child documents.

The default allowlist for a feature is one of these values:

*
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.
'none'
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. ASCII serialization

Policy Directives are represented in HTTP headers and in HTML attributes as ASCII text.

serialized-feature-policy = serialized-policy-directive *(";" serialized-policy-directive)
serialized-policy-directive = feature-identifier RWS allow-list
feature-identifier = 1*( ALPHA / DIGIT / "-")
allow-list = allow-list-value *(RWS allow-list-value)
allow-list-value = serialized-origin / "*" / "'self'" / "'src'" / "'none'"

serialized-origin is the serialization of an origin. However, the code points U+0027 ('), U+0021 (*), U+002C (,) and U+003B (;) MUST NOT appear in the serialization. If they are required, they must be percent-encoded as "%27", "%2A", "%2C" or "%3B", respectively.

The 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 ASCII serialization of one or more policy directives:.

FeaturePolicy = serialized-feature-policy *("," serialized-feature-policy)

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 allow attribute of the iframe element

partial interface HTMLIFrameElement {
    [CEReactions] attribute DOMString allow;
};

iframe elements have an "allow" attribute, which contains an ASCII-serialized policy directive.

The allowlist for the features named in the attribute may be empty; in that case, the default value for the allowlist is 'src', which represents the origin of the URL in the iframe’s src attribute.

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 constructed.

6.3. 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.3.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 must 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.

This is different from the behaviour of <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.3.2. allowpaymentrequest

The "allowpaymentrequest" iframe attribute controls access to paymentrequest.

If the iframe element has an "allow" attribute whose value contains the token "payment", then the "allowpaymentrequest" attribute must 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.

This is different from the behaviour of <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.

6.3.3. allowusermedia

The "allowusermedia" iframe attribute controls access to getUserMedia().

If the iframe element has an "allow" attribute whose value contains the token "payment", then the "allowusermedia" attribute must have no effect.

Otherwise, the presence of an "allowusermedia" attribute on an iframe will result in adding an allowlist of * for each of the "camera" and "microphone" features to the frame’s container policy, when it is constructed.

This is different from the behaviour of <iframe allow="camera; microphone">, and is for compatibility with existing uses of allowusermedia. If allow="camera; microphone" and allowusermedia are both present on an iframe element, then the more restrictive allowlist of allow="camera; microphone" will be used. Similarly, if only one of allow="camera" or allow="microphone" is present, then the more restrictive allowlist will be used for that feature, while the other will use the less restrictive *.

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

  1. Document objects have a Feature Policy, which is initially empty.
  2. Replace the existing step 12 of "Create a new browsing context" with with the following step:
  3. Replace the existing step 8 of "Initialising a new Document object" with the following step:
  4. A feature policy is enforced for a Document by setting it as the Document's Feature Policy.
  5. The "allowed to use" algorithm is replaced with the following:

    To determine whether a Document object document is allowed to use the policy-controlled-feature feature, run these steps:

    1. If document has no browsing context, then return false.

    2. If document’s browsing context's active document is not document, then return false.

    3. If document’s feature policy enables feature for the origin of document, then return true.

    4. Return false.

  6. The allow attribute is added to the IDL for the iframe element, with the description:

    The allow attribute, when specified, determines the container policy that will be used when the feature policy for the iframe's nested browsing context is initialized. Its value must be the §5.1 ASCII serialization of a policy directive.

  7. The description of the behavior of the allowfullscreen, allowpaymentrequest and allowusermedia attributes is changed to refer to this specification:

    The allowfullscreen attribute is a boolean attribute. When specified, it indicates that Document objects in the iframe element’s browsing context should be initialized with a feature policy which allows the fullscreen feature to be used from any origin. This is enforced by the Process feature policy attributes algorithm. Note that this will only allow use of the fullscreen feature if the iframe element’s node document is also allowed to use fullscreen.

    The allowpaymentrequest attribute is a boolean attribute. When specified, it indicates that Document objects in the iframe element’s browsing context should be initialized with a feature policy which allows the payment feature to be used to make payment requests from any origin. This is enforced by the Process feature policy attributes algorithm. Note that this will only allow use of the PaymentRequest interface if the iframe element’s node document is also allowed to use the feature.

    The allowusermedia attribute is a boolean attribute. When specified, it indicates that Document objects in the iframe element’s browsing context should be initialized with a feature policy which allows the camera and microphone features to be used to call getUserMedia() from any origin. This is enforced by the Process feature policy attributes algorithm. Note that this will only allow use of the getUserMedia() interface if the iframe element’s node document is also allowed to use the feature.

  8. The set the allow* flags algorithm is removed, as it is no longer referenced.
Monkey-patching! As soon as we know that this is the direction we wish to pursue, upstream all of this.

8. Algorithms

8.1. Process response policy

Given a response (response) and an origin (origin), this algorithm returns a declared feature policy.

  1. Abort these steps if the response’s header list does not contain a header whose name is "Feature-Policy".
  2. Let header be the concatenation of the values of all header fields in response’s header list whose name is "Feature-Policy", separated by U+002C (,) (according to [RFC7230, 3.2.2]).
  3. Let feature policy be the result of executing §8.2 Parse header from value and origin on header and origin.
  4. 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.

  1. Let policy be an empty ordered map.
  2. For each element returned by splitting value on commas:
    1. Let directive be the result of executing §8.3 Parse policy directive from value and origin on element and origin
    2. Run §8.4 Merge directive with declared policy on directive and policy.
  3. Return policy.

8.3. Parse policy directive from value and origin

Given a string (value) and an origin (origin) this algorithm will return a policy directive.

  1. Let directive be an empty ordered map.
  2. For each serialized-declaration returned by strictly splitting value on the delimiter U+003B (;):
    1. Let tokens be the result of splitting serialized-declaration on ASCII whitespace.
    2. If tokens is an empty list, then continue.
    3. Let feature-name be the first element of tokens.
    4. If feature-name does not identify any recognized policy-controlled feature, then continue.
    5. Let feature be the policy-controlled feature identified by feature-name.
    6. Let targetlist be the remaining elements, if any, of tokens.
    7. Let allowlist be a new allowlist.
    8. If any element of targetlist is the string "*", set allowlist to the special value *.
    9. Otherwise:
      1. Set allowlist to an new ordered set.
      2. For each element in targetlist:
        1. If element is an ASCII case-insensitive match for the string "'self'", let result be origin.
        2. Otherwise, let result be the result of executing the URL parser on element.
        3. If result is not failure:
          1. Let target be the origin of result.
          2. If target is not an opaque origin, append target to allowlist.
    10. Set directive[feature] to allowlist.
  3. Return directive

8.4. Merge directive with declared policy

Given a policy directive (directive) and a declared policy (policy), this algorithm will modify policy to account for the new directive.

  1. For each featureallowlist of directive:
    1. If policy does not contain an allowlist for feature, then set policy[feature] to allowlist.

8.5. Process feature policy attributes

Given an element (element), this algorithm returns a container policy, which may be empty.

  1. Let policy be a new policy directive.
  2. Let container policy be the result of running Parse allow attribute on the value of element’s allow attribute, with container origin set to the origin of element’s node document, and target origin set to the origin of the URL in element’s src attribute.
  3. If element is an iframe element:
    1. If element’s allowfullscreen attribute is specified, and container policy does not contain an allowlist for fullscreen,
      1. Construct a new declaration for fullscreen, whose allowlist is the special value *.
      2. Add declaration to container policy.
    2. If element’s allowpaymentrequest attribute is specified, and container policy does not contain an allowlist for payment,
      1. Construct a new declaration for payment, whose allowlist is the special value *.
      2. Add declaration to container policy.
    3. If element’s allowusermediarequest attribute is specified:
      1. If container policy does not contain an allowlist for camera,
        1. Construct a new declaration for camera, whose allowlist is the special value *.
        2. Add declaration to policy.
      2. If policy does not contain an allowlist for microphone,
        1. Construct a new declaration for microphone, allowlist is the special value *.
        2. Add declaration to container policy.
  4. Return container policy.

8.6. Parse allow attribute

Given a string (value), and two origins (container origin and target origin), this algorithm returns a policy directive.

  1. Let directive be an empty ordered map.
  2. For each serialized-declaration returned by strictly splitting value on the delimiter U+003B (;):
    1. Let tokens be the result of splitting serialized-declaration on ASCII whitespace.
    2. If tokens is an empty list, then continue.
    3. Let feature-name be the first element of tokens.
    4. If feature-name does not identify any recognized policy-controlled feature, then continue.
    5. Let feature be the policy-controlled feature identified by feature-name.
    6. Let targetlist be the remaining elements, if any, of tokens.
    7. Let allowlist be a new allowlist.
    8. If any element of targetlist is the string "*", set allowlist to the special value *.
    9. Otherwise:
      1. Set allowlist to an new ordered set.
      2. If targetlist is empty, append target origin to allowlist.
      3. For each element in targetlist:
        1. If element is an ASCII case-insensitive match for "'self'", let result be container origin.
        2. If element is an ASCII case-insensitive match for "'src'", let result be target origin.
        3. Otherwise, let result be the result of executing the URL parser on element.
        4. If result is not failure:
          1. Let target be the origin of result.
          2. If target is not an opaque origin, append target to allowlist.
    10. Set directive[feature] to allowlist.
  3. Return directive

8.7. Initialize document’s Feature Policy

Given a Document object (document), this algorithm initialises document’s Feature Policy

  1. Let inherited policies be a new ordered map.
  2. Let declared policies be a new ordered map.
  3. For each feature supported,
    1. Let isInherited be the result of running §8.9 Define an inherited policy for feature on feature and document’s browsing context.
    2. Set inherited policies[feature] to isInherited.
  4. Let policy be a new feature policy, with inherited policy set inherited policies and declared policy set declared policies.
  5. Enforce the policy policy on document.

8.8. Initialize document’s Feature Policy from response

Given a response (response) and a Document (document), this algorithm populates document’s Feature Policy

  1. Initialize document’s Feature Policy
  2. Let inherited policies be document’s Feature Policy’s inherited policy set.
  3. Let declared policies be a new ordered map.
  4. Let d be the result of running Process response policy on response and document’s origin.
  5. For each featureallowlist of d:
    1. If inherited policies[feature] is true, then set declared policies[feature] to allowlist.
  6. Let policy be a new feature policy, with inherited policy set inherited policies and declared policy set declared policies.
  7. Enforce the policy policy on document.

8.9. Define an inherited policy for feature

Given a string (feature) and a browsing context (context), this algorithm returns the inherited policy for that feature.

  1. If context is a nested browsing context:
    1. Let parent be context’s parent browsing context’s active document.
    2. Let origin be parent’s origin
    3. Let container policy be the result of running §8.5 Process feature policy attributes on context’s browsing context container.
    4. If feature is a key in container policy:
      1. If the allowlist for feature in container policy matches origin, and parent’s inherited policy for feature is Enabled, return Enabled.
      2. Otherwise return Disabled.
    5. Otherwise, if feature is enabled in parent for origin, return Enabled.
    6. Otherwise, return Disabled.
  2. Otherwise, return Enabled.

8.10. Is feature enabled in document for origin?

Given a feature (feature), a Document object (document), and an origin (origin), this algorithm returns "Disabled" if feature should be considered disabled, and "Enabled" otherwise.

  1. Let policy be document’s Feature Policy
  2. If policy’s inherited policy for feature is Disabled, return "Disabled".
  3. If feature is present in policy’s declared policy:
    1. If the allowlist for feature in policy’s declared policy matches origin, then return "Enabled".
    2. Otherwise return "Disabled".
  4. If feature’s default allowlist is *, return "Enabled".
  5. If feature’s default allowlist is 'self', and origin is same origin-domain with document’s origin, return "Enabled".
  6. 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

TODO

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSP3]
Mike West. Content Security Policy Level 3. 13 September 2016. WD. URL: https://www.w3.org/TR/CSP3/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[FULLSCREEN]
Philip Jägenstedt. Fullscreen API Standard. Living Standard. URL: https://fullscreen.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC3864]
G. Klyne; M. Nottingham; J. Mogul. Registration Procedures for Message Header Fields. September 2004. Best Current Practice. URL: https://tools.ietf.org/html/rfc3864
[URL]
Anne van Kesteren. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/
[WebIDL]
Cameron McCormack; Boris Zbarsky; Tobie Langel. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/

Informative References

[CSP2]
Mike West; Adam Barth; Daniel Veditz. Content Security Policy Level 2. 15 December 2016. REC. URL: https://www.w3.org/TR/CSP2/
[HTML5]
Ian Hickson; et al. HTML5. 28 October 2014. REC. URL: https://www.w3.org/TR/html5/

IDL Index

partial interface HTMLIFrameElement {
    [CEReactions] attribute DOMString allow;
};

Issues Index

Monkey-patching! As soon as we know that this is the direction we wish to pursue, upstream all of this.
TODO