Content Security Policy: API

Editor’s Draft,

This version:
https://w3c.github.io/webappsec-csp/api/
Version History:
https://github.com/w3c/webappsec-csp/commits/master/api/index.src.html
Feedback:
public-webappsec@w3.org with subject line “[CSP-API] … message topic …” (archives)
Editor:
(Google Inc.)
Participate:
File an issue (open issues)

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-API” in the subject, preferably like this: “[CSP-API] …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 September 2015 W3C Process Document.

Table of Contents

1. DOM API

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.

1.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 on policy’s associated policy and the Window object.
partial interface WorkerGlobalScope {
  void applySecurityPolicy(SecurityPolicy policy);
};
applySecurityPolicy(policy)
To execute this method, execute 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?

1.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 set

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 set 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 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 returns Matches when executed upon request and [[policy]]'s directive set, and false otherwise.

The nodeMatches(node) method returns true if returns Matches when executed upon node and [[policy]]'s directive set, and false otherwise.

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

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

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

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.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Ian Hickson. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[WebIDL]
Cameron McCormack; Boris Zbarsky. WebIDL Level 1. 4 August 2015. WD. URL: http://www.w3.org/TR/WebIDL-1/
[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
[WORKERS]
Ian Hickson. Web Workers. 1 May 2012. CR. URL: http://www.w3.org/TR/workers/

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;
};

Issues Index

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?