Content Security Policy Level 3

Editor’s Draft,

This version:
https://w3c.github.io/webappsec/specs/CSP3/
Latest version:
http://www.w3.org/TR/CSP3/
Feedback:
public-webappsec@w3.org with subject line “[CSP] … message topic …” (archives)
Issue Tracking:
GitHub
Inline In Spec
Editor:
(Google Inc.)
Bug Reports:
via the w3c/webappsec repository on GitHub

Abstract

This document defines a mechanism by which web developers can control the resources which a particular page can fetch or execute, as well as a number of security-relevant policy decisions.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

Changes to this document may be tracked at https://github.com/w3c/webappsec.

The (archived) public mailing list public-webappsec@w3.org (see instructions) is preferred for discussion of this specification. When sending e-mail, please put the text “CSP” in the subject, preferably like this: “[CSP] …summary of comment…

This document was produced by the Web Application Security Working Group.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 1 August 2014 W3C Process Document.

Table of Contents

1. Introduction

This section is not normative.

[INTRODUCTION GOES HERE]

1.1. Examples

1.1.1. Control Execution

The developers at https://example.com want to protect themselves against cross-site scripting attacks. They can mitigate the risk of script injection by ensuring that their trusted CDN is the only origin from which script can load and execute. Moreover, they wish to ensure that no plugins can execute in their pages' contexts. The following policy has that effect:
Content-Security-Policy: script-src https://cdn.example.com/scripts/; object-src 'none'

1.2. Goals

Content Security Policy aims to do to a few related things:

  1. Mitigate the risk of content-injection attacks by giving developers fairly granular control over

    • The resources which can be requested (and subsequently embedded or executed) on behalf of a specific Document or Worker

    • The execution of inline script

    • Dynamic code execution (via eval() and similar constructs)

    • The application of inline style

  2. Mitigate the risk of attacks which require a resource to be embedded in a malicious context ("Pixel Perfect", etc) by giving developers granular control over the origins which can embed a given resource.

  3. Provide a policy framework which allows developers to tweak security-relevant settings.

  4. Provide a reporting mechanism which allows developers to detect flaws being exploited in the wild.

1.3. Changes from Level 2

This document describes an evolution of the Content Security Policy Level 2 specification. The following is a high-level overview of the changes:

  1. The specification has been rewritten from the ground up in terms of the [FETCH] specification, which should make it simpler to integrate CSP’s requirements and restrictions with other specifications (and with Service Workers in particular).

  2. The frame-src directive, which was deprecated in CSP Level 2, has been removed.

2. Framework

A policy defines a set of allowed and restricted behaviors, and has the following attributes:

directive list

A set of directives that define the behaviors the policy allows and restricts. Unless otherwise stated, its value is the empty set.

type

Either "enforce", meaning that policy violation are actively prevented, or "report-only", meaning that policy violations are passively reported and allowed to proceed. Unless otherwise stated, its value is "enforce".

A directive defines a specific behavior, and has the following properties:

name

One of "base-uri", "child-src", "connect-src", "default-src", "font-src", "form-action", "frame-ancestors", "img-src", "media-src", "object-src", "plugin-types", "report-uri", "reports", "sandbox", "script-src", "style-src". The behaviors associated with each possible value are described in §6 Content Security Policy Directives.

value

A string. Unless otherwise stated, its value is the empty string. Parsing rules for directive’s values are described in §6 Content Security Policy Directives.

A source list directive is a specific type of directive whose value is a space-separated list of source expressions.

3. Policy Delivery

This document defines four delivery mechanisms for a resource’s policy:

  1. An HTTP response header (defined in §3.1.1 The Content-Security-Policy HTTP Response Header Field and §3.1.2 The Content-Security-Policy-Report-Only HTTP Response Header Field) which declares a policy as a string and applies it to the resource which which the header is delivered. The policy syntax is defined in §4 Policy Syntax.

  2. A meta element (defined in §3.1.3 The <meta> element), which declares a policy as a string and applies it to the resource in which the meta element is embedded. The policy syntax is defined in §4 Policy Syntax.

  3. Inheritance, which applies a policy to a nested browsing context in certain circumstances, as defined in §3.2 Implicit Delivery.

  4. A JavaScript interface (defined in §3.3 Imperative Delivery).

3.1. Declarative Delivery

3.1.1. The Content-Security-Policy HTTP Response Header Field

The Content-Security-Policy HTTP response header field is the preferred mechanism for delivering a policy from a server to a client. The header’s value is represented by the following ABNF [RFC5234]:

Content-Security-Policy = 1#policy-token
Content-Security-Policy: script-src 'self';
                         reports /csp-reporting-endpoint

A server MAY send different Content-Security-Policy header field values with different representations of the same resource.

A server SHOULD NOT send more than one HTTP response header field named "Content-Security-Policy" with a given resource representation. The user agent MUST enforce each of the policies contained in each such header field as described in §7.2 Policy Application Algorithms.

3.1.2. The Content-Security-Policy-Report-Only HTTP Response Header Field

The Content-Security-Policy-Report-Only HTTP response header field allows web developers to experiment with policies by monitoring (but not enforcing) their effects. The header’s value is represented by the following ABNF [RFC5234]:

Content-Security-Policy-Report-Only = 1#policy-token

This header field allows developers to piece together their security policy in an iterative fashion, deploying a report-only policy based on their best estimate of how their site behaves, watching for violation reports, and then moving to an enforced policy once they’ve gained confidence in that behavior.

Content-Security-Policy-Report-Only: script-src 'self';
                                     reports /csp-reporting-endpoint

A server MAY send different Content-Security-Policy-Report-Only header field values with different representations of the same resource.

A server SHOULD NOT send more than one HTTP response header field named "Content-Security-Policy-Report-Only" with a given resource representation. The user agent MUST monitor each of the policies contained in each such header field as described in §7.2 Policy Application Algorithms.

Note: The Content-Security-Policy-Report-Only header is not supported inside a meta element.

3.1.3. 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 "Content-Security-Policy". For example:

<meta http-equiv="Content-Security-Policy" content="script-src 'self'">

Implementation details can be found in §7.2.4 Apply policies to document via <meta>.

Authors are strongly encouraged to place meta elements as early in the document as possible, because policies in meta elements are not applied to content which precedes them. In particular, note that resources fetched or prefetched using the Link HTTP response header field, and resources fetched or prefetched using link and script elements which precede a meta-delivered policy will not be blocked.

Note: A policy specified via a meta element will be enforced along with any other policies active for the protected resource, regardless of where they’re specified. The general impact of enforcing multiple policies is described in §9.1 The effect of multiple policies.

Note: Modifications to the content attribute of a meta element after the element has been parsed will be ignored.

Note: The Content-Security-Policy-Report-Only header is not supported inside a meta element.

3.2. Implicit Delivery

Resources with local schemes (e.g. about, blob:, data:, and filesystem:), as well as resouces embedded via iframe's srcdoc attribute, are considered same-origin with the origin that created them, but have no mechanism for header-based policy delivery. To ensure that this property doesn’t allow a trivial bypass of a page’s policy (by creating a blob: and embedding it in an iframe, for instance), these kinds of resources inherit the policy of their embedding context, as described in §7.2.1 Apply policies to a Document created via a response, §7.2.3 Apply policies to a Worker, and §7.2.2 Apply policies to an IFrame srcdoc Document.

We should consider extending this to include auxiliary browsing contexts, not just nested browsing contexts. <https://github.com/w3c/webappsec/issues/451>

3.3. Imperative Delivery

Developers may manipulate a page’s policy via a JavaScript API which allows construction of SecurityPolicy objects, and the application of those objects to an environment settings object.

3.3.1. Applying a Policy

A SecurityPolicy can be applied to an environment settings object via the following interfaces:

partial interface Window {
  void applySecurityPolicy(SecurityPolicy policy);
};
applySecurityPolicy(policy)
To execute this method, execute §7.2.5 Apply policy to global object on policy’s associated policy and the Window object.
partial interface WorkerGlobalScope {
  void applySecurityPolicy(SecurityPolicy policy);
};
applySecurityPolicy(policy)
To execute this method, execute §7.2.5 Apply policy to global object on policy’s associated policy and the WorkerGlobalScope object.
To apply the policy script-src 'self'; object-src 'none' from JavaScript inside a Worker or Document, execute the following code:
var policy = new SecurityPolicy("script-src 'self'; object-src 'none'");
self.applySecurityPolicy(policy);

Maybe this makes more sense as `window.csp.apply()`? Which would also allow `window.csp.enforced` and `window.csp.monitored` as sequences of SecurityPolicy objects?

3.3.2. SecurityPolicy Interface

A policy object is defined via the following IDL:

enum SecurityPolicyType {
  "enforce",
  "report-only"
};

[Constructor(DOMString policy, SecurityPolicyType type), Exposed=(Window,Worker)]
interface SecurityPolicy {
  boolean requestMatches(Request request);
  boolean nodeMatches(Node node);
  
  readonly attribute FrozenArray<SecurityPolicyDirective> directives;
  readonly attribute SecurityPolicyType type;
  readonly attribute USVString reportingEndpoint;
};

A SecurityPolicy object has an internal slot named [[policy]], which contains a policy. Unless otherwise stated, its value is null.

The directives attribute’s getter returns a list of SecurityPolicyDirectives corresponding to [[policy]]'s directive list

The type attribute’s getter returns the value of [[policy]]'s type.

The reportingEndpoint attribute’s getter returns the serialization of the value of the directive in [[policy]]'s directive list with a name of "report-uri", if present. If no such directive is present, the empty string is returned.

The SecurityPolicy(policy, type) constructor, when invoked, MUST execute the following steps:

  1. Let policy list be the result of executing §7.3.1 Parse string as a Content Security Policy on policy.

  2. If policy list does not have exactly one element, throw a SyntaxError exception, and abort the remaining steps.

  3. Set this@[[policy]] to the only element in policy list.

  4. Return this.

The requestMatches(request) method returns true if §7.4.1 Does request match directive list? returns Matches when executed upon request and [[policy]]'s directive list, and false otherwise.

The nodeMatches(node) method returns true if §7.4.4 Does node match directive list? returns Matches when executed upon node and [[policy]]'s directive list, and false otherwise.

3.3.3. SecurityPolicyDirective Interface

Policy objects contain a list of directives, each defined according to the following IDL:

enum DirectiveName {
  "base-uri",
  "child-src",
  "connect-src",
  "default-src",
  "font-src",
  "form-action",
  "frame-ancestors",
  "img-src",
  "media-src",
  "object-src",
  "plugin-types",
  "report-uri",
  "reports",
  "sandbox",
  "script-src",
  "style-src"
};

[Constructor(DOMString name, DOMString value), Exposed=(Window,Worker)]
interface SecurityPolicyDirective {
  boolean requestMatches(Request request);
  boolean nodeMatches(Node node);

  readonly attribute DirectiveName name;  
};

A SecurityPolicyDirective object has an internal slot named [[directive]], which contains a directive. Unless otherwise specified, its value is null.

The name attribute’s getter returns [[directive]]'s name.

The value attribute’s getter returns [[directive]]'s value.

The SecurityPolicyDirective(name, value) constructor, when invoked, MUST execute the following steps:

  1. If name is not a valid DirectiveName, throw a SyntaxError exception, and abort the remaining steps.

  2. Let directive be a new directive with a name of name and a value of value.

  3. Set this@[[directive]] to directive.

  4. Return this.

The requestMatches(request) method returns true.

The nodeMatches(node) method returns true.

Note: Directives which operate on either Requests or Nodes are expected to inherit from SecurityPolicyDirective and override these method implementations. SourceListDirective is one example of this.

3.3.4. SourceListDirective Interface

Directives whose values are source lists are parsed into SourceListDirective objects (which subclass SecurityPolicyDirective). These are defined according to the following IDL:

[Constructor(DOMString name, DOMString value), Exposed=(Window,Worker)]
interface SourceListDirective : SecurityPolicyDirective {
  readonly attribute FrozenArray<SourceExpression> sources;
};

The SourceListDirective(name, value) constructor, when invoked, MUST execute the following steps:

  1. If name is not a valid DirectiveName, throw a SyntaxError exception, and abort the remaining steps.

  2. Let directive be a new directive with a name of name and a value of value.

  3. Set this@[[directive]] to directive.

  4. this@Set sources to the result of executing §7.3.2 Parse string as a source list on value.

  5. Return this.

The requestMatches(request) method, when invoked, MUST execute the following steps:

  1. Let url be request’s url.

  2. For each expression in this object’s sources attribute:

    1. If expression’s urlMatches(url) returns true when executed upon url, return true.

  3. Return false.

The nodeMatches(node) method, when invoked, MUST execute the following steps:

  1. For each expression in this object’s sources attribute:

    1. If expression’s nodeMatches(node) returns true when executed upon node, return true.

  2. Return false.

3.3.5. SourceExpression Interface

SourceListDirective objects' sources attribute contains the list of source expressions that make up the directive’s value. These are represented as SourceExpression objects according to the following IDL:

[Constructor(DOMString value), Exposed=(Window,Worker)]
interface SourceExpression {
  boolean urlMatches(USVString url);
  boolean nodeMatches(Node node);

  readonly attribute DOMString value;
};
value, of type DOMString, readonly
The expression’s value. script-src https://example.com/ 'nonce-abcde' will, for example, produce two SourceExpression objects, one with a value of "https://example.com/", the other with a value of "'nonce-abcde'".
urlMatches(url)
This method returns true if executing §7.4.3 Does url match source expression? on url and the object’s value attribute returns Matches, and false otherwise.
Parameter Type Nullable Optional Description
url USVString The URL to match against the SourceExpression.
Arguments for the SourceExpression.urlMatches(url) method.
nodeMatches(node)
This method returns true if executing §7.4.6 Does node match source expression? on node and the object’s value attribute returns Matches, and false otherwise.
Parameter Type Nullable Optional Description
node Node The Node which will be matched against the directive.
Arguments for the SourceExpression.nodeMatches(node) method.

4. Policy Syntax

A serialized Content Security Policy consists of a semicolon-delimited list of directives. Each directive consists of a key and (optionally) a value, defined by the following ABNF [RFC5234]:

policy-token = directive-token *( OWS ";" [ OWS directive-token ] )
directive-token = directive-name [ RWS directive-value ]
directive-name = 1*( ALPHA / DIGIT / "-" )
directive-value = *( WSP / <VCHAR except ";" and ","> )
Note: The BWS, OWS, and RWS rules are defined in [RFC7230]. ALPHA, DIGIT, VCHAR, and WSP are defined in [RFC5234].

4.1. Source List Syntax

The syntax for individual directives is defined in §6 Content Security Policy Directives, though many directives share a common source list syntax defined below.

A source list represents a set of locations from which content of a specified type can be fetched and potentially embedded or executed. Locations are represented by one of the following types of source expression:

  1. Keywords such as 'none' and 'self' (which match nothing and the current URL’s origin, respectively)

  2. Serialized URLs such as https://example.com/path/to/file.js (which matches a specific file) or https://example.com/ (which matches everything on that origin)

  3. Schemes such as https: (which matches any resource having the specified scheme)

  4. Hosts such as example.com (which matches any resource on the host, regardless of scheme) or *.example.com (which matches any resource on the host or any of its subdomains (and any of its subdomains' subdomains, and so on))

  5. Nonces such as 'nonce-qwertyu12345' (which can match specific elements on a page)

  6. Digests such as 'sha256-abcd...' (which can match specific elements on a page)

These representations are defined by the following ABNF [RFC5234]:

source-list       = source-expression *( RWS source-expression )
                    / "'none'"
source-expression = scheme-source / host-source / keyword-source
                    / nonce-source / hash-source

; Schemes: `scheme:`
scheme-source = scheme ":"

; Hosts: `example.com` / `*.example.com` / `https://*.example.com:12/path/to/file.js`
host-source = [ scheme-part "://" ] host-part [ port-part ] [ path-part ]
scheme-part = scheme
host-part   = "*" / [ "*." ] 1*host-char *( "." 1*host-char )
host-char   = ALPHA / DIGIT / "-"
port-part   = ":" ( 1*DIGIT / "*" )
path-part   = path
   
; Keywords:
keyword-source = "'self'" / "'unsafe-inline'" / "'unsafe-eval'" 

; Nonces: 'nonce-[nonce goes here]'
nonce-source  = "'nonce-" base64-value "'"
base64-value  = 1*( ALPHA / DIGIT / "+" / "/" )*2( "=" ) 

; Digests: 'sha256-[digest goes here]'
hash-source    = "'" hash-algorithm "-" base64-value "'"
hash-algorithm = "sha256" / "sha384" / "sha512"

Note: The scheme and path rules are defined in [RFC3986].

The host-char production intentionally contains only ASCII characters; internationalized domain names cannot be entered directly into a policy string, but instead MUST be Punycode-encoded [RFC3492]. For example, the domain üüüüüü.de MUST be represented as xn--tdaaaaaa.de.

Note: Though IP address do match the grammar above, only 127.0.0.1 will actually match a URL when used in a source expression (see §7.4.2 Does url match source list? for details). The security properties of IP addresses are suspect, and authors ought to prefer hostnames whenever possible.

4.1.1. The nonce attribute

Nonce sources require a new nonce attribute to be added to both script and style elements.

partial interface HTMLScriptElement {
  attribute DOMString nonce;
};
nonce, of type DOMString
This attribute reflects the value of the element’s nonce content attribute.
partial interface HTMLStyleElement {
  attribute DOMString nonce;
};
nonce, of type DOMString
This attribute reflects the value of the element’s nonce content attribute.

5. Reporting

6. Content Security Policy Directives

This specification defines a number of types of directives which allow developers to control certain aspects of their sites' behavior. The defined directives fall into one of several categories:

  1. Request Directives control the locations from which certain resource types may be loaded. For instance, script-src allows developers to whitelist trusted sources of script to execute on a page, while font-src controls the sources of web fonts.

  2. ...

To mitigate the risk of cross-site scripting attacks, web developers SHOULD include directives that regulate sources of script and plugins. They can do so by including:

In either case, developers SHOULD NOT include either 'unsafe-inline', or data: as valid sources in their policies. Both enable XSS attacks by allowing code to be included directly in the document itself; they are best avoided completely.

6.1. Request Directives

6.1.1. child-src

The child-src directive governs the creation of nested browsing contexts and Worker execution contexts. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "child-src"
directive-value = source-list
Given a page with the following Content Security Policy:
Content-Security-Policy: child-src https://example.com/

Fetches for the following code will all return network errors, as the URLs provided do not match child-src’s source list:

<iframe src="https://not-example.com"></iframe>
<script>
  var blockedWorker = new Worker("data:application/javascript,...");
</script>

6.1.2. connect-src

The connect-src directive restricts the URLs which can be loaded using script interfaces such as those defined in [XMLHttpRequest] and [FETCH]. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "connect-src"
directive-value = source-list

6.1.3. default-src

The default-src directive serves as a fallback for the other request directives. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "default-src"
directive-value = source-list

6.1.4. font-src

The font-src directive restricts the URLs from which font resources may be loaded. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "font-src"
directive-value = source-list

6.1.5. img-src

The img-src directive restricts the URLs from which image resources may be loaded. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "img-src"
directive-value = source-list

6.1.6. media-src

The media-src directive restricts the URLs from which video, audio, and associated text track resources may be loaded. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "media-src"
directive-value = source-list

6.1.7. object-src

The object-src directive restricts the URLs from which plugins may be loaded. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "object-src"
directive-value = source-list

6.1.8. script-src

The script-src directive restricts the locations from which scripts may be executed. This includes not only URLs loaded directly into script elements, but also things like inline script blocks and XSLT stylesheets [XSLT] which can trigger script execution. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "script-src"
directive-value = source-list

6.1.9. style-src

The style-src directive restricts the locations from which style may be applied to a Document. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "style-src"
directive-value = source-list

6.2. Grabbag

6.2.1. base-uri

The base-uri directive restricts the URLs which can be used in a Document's base element. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "base-uri"
directive-value = <URL> ; TODO: Figure out what to use here.

6.2.2. form-action

6.2.3. frame-ancestors

6.2.4. plugin-types

6.2.5. sandbox

6.3. Reporting Directives

6.3.1. report-uri

The report-uri directive is deprecated. Please use the reports directive instead.

6.3.2. reports

The reports directive defines the endpoint to which violation reports are sent. The syntax for the directive’s name and value is described by the following ABNF:

directive-name  = "reports"
directive-value = <URL> ; TODO: Figure out what to use here.

7. Algorithms

7.1. Fetch Interface

This specification provides two algorithms which allow Fetch to make decisions about whether or not a particular request should be blocked based on its client's Content Security Policy [FETCH]. The policy check occurs twice: once at the top of Fetch, ensuring that outgoing requests satisfy the relevant policy; and once at the bottom, ensuring that incoming responses match as well (as they could have been modified in interesting ways by an intermediate Service Worker). These algorithms can be considered the public interface to the Content Security Policy specification:

7.1.1. Should request be blocked by Content Security Policy?

Given a request (request), this algorithm returns Blocked or Allowed based on request’s client's Content Security Policy.

Note: [FETCH] calls this algorithm as step #3 of its Main Fetch algorithm.

  1. Let client be request’s client.

  2. Return Blocked.

We should probably expand on this definition a bit.

7.1.2. Should response to request be blocked by Content Security Policy?

Given a response (response) and a request (request), this algorithm returns Blocked or Allowed based on request’s client's Content Security Policy.

Note: [FETCH] calls this algorithm as step #12 of its Main Fetch algorithm.

  1. Let client be request’s client.

  2. Return Blocked.

We should probably expand on this definition a bit.

7.2. Policy Application Algorithms

Monkey patches gonna monkey patch. Talk to WHATWG / WICG.

Each of the delivery mechanisms specified in §3 Policy Delivery can be used to add values to one of three properties this specification adds to environment settings objects to store the relevant policy data for a resource:

enforced Content Security Policies

A set of policies which are to be enforced for the settings object. This property’s value is the empty set unless otherwise specified.

monitored Content Security Policies

A list of policies which are to be monitored for the settings object. This property’s value is the empty list unless otherwise specified.

inherits Content Security Policies

A boolean value signifying whether or not the policies of an embedding Document ought to be applied (as described in §7.5.1 Gather policies for environment settings object and disposition). This property is false unless otherwise specified.

A policy is enforced for an environment settings object by inserting it into the object’s enforced Content Security Policies list. A string is enforced by enforcing each result of executing §7.3.1 Parse string as a Content Security Policy on the string.

A policy is monitored for an environment settings object by inserting it into the object’s monitored Content Security Policies list. A string is monitored by monitoring each result of executing §7.3.1 Parse string as a Content Security Policy on the string.

7.2.1. Apply policies to a Document created via a response

When creating a Document object (document) for a response (response):

  1. If response’s url's scheme is a local scheme:

    1. Set document’s incumbent settings object’s inherits Content Security Policies property to true.

  2. Otherwise:

    1. Execute §7.2.6 Apply policies from header list to environment settings object on response’s header list and document’s incumbent settings object.

7.2.2. Apply policies to an IFrame srcdoc Document

When creating a Document object (document) for an iframe srcdoc document:

  1. Set document’s incumbent settings object’s inherits Content Security Policies property to true.

7.2.3. Apply policies to a Worker

When running a worker worker for environment settings object settings successfully executes a Fetch in its current step 4:

  1. If response’s url's scheme is a local scheme:

    1. Set settings inherits Content Security Policies property to true.

  2. Otherwise:

    1. Execute §7.2.6 Apply policies from header list to environment settings object on the response’s header list and settings.

Note: This is using the WHATWG’s definition of "run a worker", because the W3C’s version has no concept of environment settings objects.

Does this cover Service Workers?

7.2.4. Apply policies to document via <meta>

Monkey-patching! Move this to HTML.

Add the following entry to the pragma directives for the meta element:

Content security policy (http-equiv="content-security-policy")
  1. If the Document’s head element is not an ancestor of the meta element, abort these steps.
  2. If the meta element lacks a content attribute, abort these steps.
  3. Let content be the value of the content attribute of the meta element.
  4. Let policy be the result of executing §7.3.1 Parse string as a Content Security Policy on content.
  5. Remove all occurrences of report-uri, frame-ancestors, and sandbox directives from policy’s directive set.

    Note: User agents are encouraged to issue a warning to developers if one or more of these directives are included in a policy delivered via meta.

    Wire all this up once the directives exist and the policy object is defined.

  6. Enforce policy on the incumbent settings object.

7.2.5. Apply policy to global object

  1. Let settings be the relevant settings object for global object.

  2. If policy’s type attribute is "enforce", enforce policy for settings.

  3. Otherwise, policy’s type attribute is "report-only", so monitor policy for settings.

7.2.6. Apply policies from header list to environment settings object

Given a response’s header list (header list) and an environment settings object (settings), this algorithm extracts the policies which ought to be enforced and monitored for the settings object, and does so:

  1. Let policy to enforce be the result of parsing Content-Security-Policy in header list.

  2. Let policies be the result of executing §7.3.1 Parse string as a Content Security Policy on policy to enforce.

  3. Enforce each policy object in policies on settings.

  4. Let policy to monitor be the result of parsing Content-Security-Policy-Report-Only in header list.

  5. Let policies be the result of executing §7.3.1 Parse string as a Content Security Policy on policy to monitor.

  6. Monitor each policy object in policies on settings.

7.3. Parsing Algorithms

7.3.1. Parse string as a Content Security Policy

Given a policy string (string), this algorithm will return a list of policies. In the case of a fatal parse error, this list will be empty.

7.3.2. Parse string as a source list

Given a source list directive’s value, this algorithm will return a list of source expressions. In the case of a fatal parse error, this list will be empty.

7.4. Matching Algorithms

7.4.1. Does request match directive list?

Parse the request to determine which directive applies, find the relevant directive in the list, and call §7.4.2 Does url match source list?.

7.4.2. Does url match source list?

Given a URL (url) and a source list (list), this algorithm returns Matches or Does Not Match.

  1. For each expression in list:

    1. If §7.4.3 Does url match source expression? returns Matches when executed upon url and expression, then return Matches

  2. Return Does Not Match.

7.4.3. Does url match source expression?

Given a URL (url) and a source expression (source), this algorithm returns Matches or Does Not Match.

  1. Return Does Not Match.

This might need a bit of polishing.

7.4.4. Does node match directive list?

Parse the node to determine which directive applies, find the relevant directive in the list, and call §7.4.5 Does node match source list?.

7.4.5. Does node match source list?

Given a Node (node) and a source list (list), this algorithm returns Matches or Does Not Match.

  1. For each expression in list:

    1. If §7.4.6 Does node match source expression? returns Matches when executed upon node and expression, then return Matches

  2. Return Does Not Match.

7.4.6. Does node match source expression?

Given a Node (url) and a source expression (source), this algorithm returns Matches or Does Not Match.

  1. Return Does Not Match.

This might need a bit of polishing.

7.5. Internal Helpers

These algorithms are part of the internal processing model of Content Security Policy, and are not meant to be called from other specifications.

7.5.1. Gather policies for environment settings object and disposition

Given an environment settings object (settings), and a disposition of either Enforce or Monitor this algorithm returns a list of policies which ought to be considered.

In order to properly deal with inheritance, this algorithm will walk through a Document document’s embedding documents: the Document through which document’s browsing context is nested.

  1. Let policies be an empty list.

  2. Let effective policies be settings' enforced Content Security Policies attribute if disposition is Enforce, and settings' monitored Content Security Policies otherwise.

  3. For each policy in effective policies:

    1. Push policy into policies.

  4. If settings' inherits Content Security Policies attribute is true:

    1. If settings' global object is a Window:

      1. Let parent be settings' responsible browsing context’s active Document’s creator Document’s global object’s relevant settings object.

      2. Let policies to inherit be the result of executing §7.5.1 Gather policies for environment settings object and disposition on parent and disposition.

      3. For each policy in policies to inherit:

        1. Push policy into policies.

    2. Otherwise, settings' global object is a WorkerGlobalScope:

      1. I have no idea what to do here. Anne suggests monkey-patching run a worker.

  5. Return policies.

7.5.2. Get the effective directive for Request from policy

Given a Request object (request), and a policy (policy), this algorithm returns the effective directive which controls the request. If no such directive is present in the given policy, this algorithm returns null.

  1. Return null.

8. Security Considerations

8.1. Nonce Reuse

Nonces override the other restrictions present in the directive in which they’re delivered. It is critical, then, that they remain unguessable, as bypassing a resource’s policy is otherwise trivial.

If a server delivers a nonce-source expression as part of a policy string, the server MUST generate a unique value each time it transmits a policy. The generated value SHOULD be at least 128 bits long (before encoding), and SHOULD be generated via a cryptographically secure random number generator in order to ensure that the value is difficult for an attacker to predict.

Note: Using a nonce to whitelist inline script or style is less secure than not using a nonce, as nonces override the restrictions in the directive in which they are present. An attacker who can gain access to the nonce can execute whatever script they like, whenever they like. That said, nonces provide a substantial improvement over 'unsafe-inline' when layering a content security policy on top of old code. When considering 'unsafe-inline', authors are encouraged to consider nonces (or hashes) instead.

9. Authoring Considerations

9.1. The effect of multiple policies

This section is not normative.

The above sections note that when multiple policies are present, each must be enforced or reported, according to its type. An example will help clarify how that ought to work in practice. The behavior of an XMLHttpRequest might seem unclear given a site that, for whatever reason, delivered the following HTTP headers:

Content-Security-Policy: default-src 'self' http://example.com http://example.net;
                         connect-src 'none';
Content-Security-Policy: connect-src http://example.com/;
                         script-src http://example.com/

Is a connection to example.com allowed or not? The short answer is that the connection is not allowed. Enforcing both policies means that a potential connection would have to pass through both unscathed. Even though the second policy would allow this connection, the first policy contains connect-src 'none', so its enforcement blocks the connection. The impact is that adding additional policies to the list of policies to enforce can only further restrict the capabilities of the protected resource.

To demonstrate that further, consider a script tag on this page. The first policy would lock scripts down to 'self', http://example.com and http://example.net via the default-src directive. The second, however, would only allow script from http://example.com/. Script will only load if it meets both policy’s criteria: in this case, the only origin that can match is http://example.com, as both policies allow it.

10. IANA Considerations

The permanent message header field registry should be updated with the following registration: [RFC3864]

10.1. Content-Security-Policy

Header field name
Content-Security-Policy
Applicable protocol
http
Status
standard
Author/Change controller
W3C
Specification document
This specification (See §3.1.1 The Content-Security-Policy HTTP Response Header Field)

11. Acknowledgements

Lots of people are awesome.

Conformance

Document conventions

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.

Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

Conformance Classes

A conformant user agent must implement all the requirements listed in this specification that are applicable to user agents.

A conformant server must implement all the requirements listed in this specification that are applicable to servers.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[ES2015]
Allen Wirfs-Brock. ECMAScript® 2015 Language Specification. URL: http://www.ecma-international.org/ecma-262/6.0/index.html
[FETCH]
Anne van Kesteren. Fetch. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Ian Hickson. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC3492]
Adam M. Costello. Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA). REC. URL: http://www.ietf.org/rfc/rfc3492.txt
[RFC3864]
Graham Klyne; Mark Nottingham; Jeffrey C. Mogul. Registration Procedures for Message Header Fields. RFC. URL: http://www.ietf.org/rfc/rfc3864.txt
[RFC7230]
Roy T. Fielding; Julian F. Reschke. HTTP/1.1 Message Syntax and Routing. RFC. URL: http://www.ietf.org/rfc/rfc7230.txt
[RFC7231]
Roy T. Fielding; Julian F. Reschke. HTTP/1.1 Semantics and Content. RFC. URL: http://www.ietf.org/rfc/rfc7231.txt
[URL]
Anne van Kesteren. URL. Living Standard. URL: https://url.spec.whatwg.org/
[WebIDL]
Cameron McCormack. Web IDL. 19 April 2012. CR. URL: http://www.w3.org/TR/WebIDL/
[DOM]
Anne van Kesteren; et al. W3C DOM4. 18 June 2015. LCWD. URL: http://www.w3.org/TR/dom/
[HTML5]
Ian Hickson; et al. HTML5. 28 October 2014. REC. URL: http://www.w3.org/TR/html5/
[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
[RFC3986]
T. Berners-Lee; R. Fielding; L. Masinter. Uniform Resource Identifier (URI): Generic Syntax. January 2005. Internet Standard. URL: https://tools.ietf.org/html/rfc3986
[RFC5234]
D. Crocker, Ed.; P. Overell. Augmented BNF for Syntax Specifications: ABNF. January 2008. Internet Standard. URL: https://tools.ietf.org/html/rfc5234
[WORKERS]
Ian Hickson. Web Workers. 1 May 2012. CR. URL: http://www.w3.org/TR/workers/

Informative References

[XMLHttpRequest]
Anne van Kesteren; et al. XMLHttpRequest Level 1. 30 January 2014. WD. URL: http://www.w3.org/TR/XMLHttpRequest/
[XSLT]
James Clark. XSL Transformations (XSLT) Version 1.0. 16 November 1999. REC. URL: http://www.w3.org/TR/xslt

IDL Index

partial interface Window {
  void applySecurityPolicy(SecurityPolicy policy);
};

partial interface WorkerGlobalScope {
  void applySecurityPolicy(SecurityPolicy policy);
};

enum SecurityPolicyType {
  "enforce",
  "report-only"
};

[Constructor(DOMString policy, SecurityPolicyType type), Exposed=(Window,Worker)]
interface SecurityPolicy {
  boolean requestMatches(Request request);
  boolean nodeMatches(Node node);
  
  readonly attribute FrozenArray<SecurityPolicyDirective> directives;
  readonly attribute SecurityPolicyType type;
  readonly attribute USVString reportingEndpoint;
};

enum DirectiveName {
  "base-uri",
  "child-src",
  "connect-src",
  "default-src",
  "font-src",
  "form-action",
  "frame-ancestors",
  "img-src",
  "media-src",
  "object-src",
  "plugin-types",
  "report-uri",
  "reports",
  "sandbox",
  "script-src",
  "style-src"
};

[Constructor(DOMString name, DOMString value), Exposed=(Window,Worker)]
interface SecurityPolicyDirective {
  boolean requestMatches(Request request);
  boolean nodeMatches(Node node);

  readonly attribute DirectiveName name;  
};

[Constructor(DOMString name, DOMString value), Exposed=(Window,Worker)]
interface SourceListDirective : SecurityPolicyDirective {
  readonly attribute FrozenArray<SourceExpression> sources;
};

[Constructor(DOMString value), Exposed=(Window,Worker)]
interface SourceExpression {
  boolean urlMatches(USVString url);
  boolean nodeMatches(Node node);

  readonly attribute DOMString value;
};

partial interface HTMLScriptElement {
  attribute DOMString nonce;
};

partial interface HTMLStyleElement {
  attribute DOMString nonce;
};

Issues Index

We should consider extending this to include auxiliary browsing contexts, not just nested browsing contexts. <https://github.com/w3c/webappsec/issues/451>
Maybe this makes more sense as `window.csp.apply()`? Which would also allow `window.csp.enforced` and `window.csp.monitored` as sequences of SecurityPolicy objects?
We should probably expand on this definition a bit.
We should probably expand on this definition a bit.
Monkey patches gonna monkey patch. Talk to WHATWG / WICG.
Does this cover Service Workers?
Monkey-patching! Move this to HTML.
Wire all this up once the directives exist and the policy object is defined.
Parse the request to determine which directive applies, find the relevant directive in the list, and call §7.4.2 Does url match source list?.
This might need a bit of polishing.
Parse the node to determine which directive applies, find the relevant directive in the list, and call §7.4.5 Does node match source list?.
This might need a bit of polishing.
I have no idea what to do here. Anne suggests monkey-patching run a worker.