Content Security Policy: Embedded Enforcement

Content Security Policy: Embedded Enforcement

W3C First Public Working Draft,

This version:
http://www.w3.org/TR/2015/WD-csp-embedded-enforcement-20151215/
Latest version:
http://www.w3.org/TR/csp-embedded-enforcement/
Editor's Draft:
https://w3c.github.io/webappsec-csp/embedded/
Version History:
https://github.com/w3c/webappsec-csp/commits/master/embedded/index.src.html
Feedback:
public-webappsec@w3.org with subject line “[csp-embedded-enforcement] … message topic …” (archives)
Editor:
(Google Inc.)
Participate:
File an issue (open issues)

Abstract

This document defines a mechanism by which a web page can embed a nested browsing context if and only if it agrees to enforce a particular set of restrictions upon itself.

Status of this document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was published by the Web Application Security Working Group as a Working Draft. This document is intended to become a W3C Recommendation.

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-embedded-enforcement” in the subject, preferably like this: “[csp-embedded-enforcement] …summary of comment…

This document is a First Public Working Draft.

Publication as a First Public Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

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

This section is not normative.

Content Security Policy is a great defense against cross-site scripting attacks, allowing developers to harden their own sites against injection of malicious script, style, and other resource types. It does not, however, give developers the ability to apply restrictions to third-party content loaded in via <iframe>. Allowing CSP to apply directly to these third-party contexts would be dangerous; CSP gives quite granular control over resource loading, and it’s very possible to introduce vulnerabilities into an otherwise secure page by denying it access to particular scripts. We’ve seen these kinds of issues in past features such as X-XSS-Protection, so we must be careful to avoid reintroducing them in a new form.

That said, it would be quite useful to be able to place restrictions upon widgets, advertisements, and other kinds of third-party content. This document proposes a mechanism which relies on an explicit opt-in from the embedded content, which ought to make it possible for widgets to cooperate with their embedders to negotiate a reasonable set of restrictions.

In short, the embedder proposes a Content Security Policy as an attribute on the <iframe> element. This policy is transmitted along with the HTTP request for the framed content in an Embedding-CSP header. If the embedded content can accept that policy, it may do so by returning the proposed policy in a Content-Security-Policy header along with the response.

If the response contains a policy identical to the policy which the embedder requested, the user agent will render the embedded content. If no such policy is present, the response will be blocked.

1.1. Examples

MegaCorp Inc. wishes to ensure that the advertisements that run on its various publications are locked down to include script from trusted origins that have been audited for safety. They can do so by including the advertisement via an iframe element with a csp attribute:
<iframe src="https://advertisements-r-us.example.com/ad1.cfm"
        csp="script-src https://trusted-cdn.example.com/">
</iframe>

This will generate a request to advertisements-r-us.example.com that has an Embedding-CSP header, as follows:

GET / HTTP/1.1
Host: advertisements-r-us.example.com
...
Embedding-CSP: script-src https://trusted-cdn.example.com/
...

The advertisment will only load if it is delivered with a Content Security Policy which exactly matches the csp attribute’s value. One way to do so is to send the requested policy:

HTTP/1.1 200 OK
...
Content-Security-Policy: script-src https://trusted-cdn.example.com/

The server might want to futher restrict the document, however. Perhaps it wishes to ensure that plugins will not be loaded. It can do so by sending another policy with additional restrictions:

HTTP/1.1 200 OK
...
Content-Security-Policy: script-src https://trusted-cdn.example.com/,
                         object-src 'none'

The "," in the Content-Security-Policy header’s value splits the string into two serialized policies, each of which is enforced.

2. Framework

2.1. Specifying a Policy Requirement

Monkey-patching HTML.

Browsing contexts have an iframe security policy attribute, which is null unless otherwise specified.

iframe elements have a csp attribute which specifies the policy that an embedded document must agree to enforce upon itself.

partial interface HTMLIFrameElement {
  attribute DOMString csp;
};

HTMLIFrameElement's csp IDL attribute reflects the value of the element’s csp content attribute.

When an iframe element with a csp attribute has its nested browsing context created (before the intial about:blank Document is created), and when an iframe element’s csp attribute is set or changed while it has a nested browsing context, the user agent must set the nested browsing context’s iframe security policy to the result of executing the parse a serialized policy algorithm on the csp attribute’s value.

During the navigate algorithm, perform the following step after the current step 19. At this point, the user agent has fetched a response which it is about to begin parsing, and redirects have been processed:

  1. If the algorithm in §3.1 Is response blocked by context’s iframe security policy? returns Blocked when executed upon the resource and the browsing context being navigated, abort these steps. The user agent MAY indicate to the user that navigation has been aborted for security reasons.

2.2. The Embedding-CSP HTTP Request Header

In order to ensure that the embedded resource can decide whether or not it is willing to adhere to the embedder’s requirements, the policy expressed in an iframe's csp attribute is communicated along with some requests via an "Embedding-CSP" HTTP request header. The header’s value is represented by the following ABNF [RFC5234]:

Embedding-CSP = serialized-policy

A user agent MUST NOT send more than one HTTP response header field named "Embedding-CSP", and any such header MUST NOT contain more than one serialized-policy.

Step ~15 of the navigate algorithm needs to be adjusted to add an Embedding-CSP header to a navigational request iff the navigation targets a nested browsing context, and if the browsing context container is an iframe element with a csp attribute. This should be pretty straightforward once the algorithm is rewritten in terms of Fetch, but is a bit tricky today.

3. Algorithms

3.1. Is response blocked by context’s iframe security policy?

Given a response (response) and a browsing context (context), this algorithm returns Allowed or Blocked as appropriate:

  1. Let embedding policy be the value of context’s iframe security policy.

  2. Let policy list be the value of response’s CSP list.

  3. If the §3.2 Is policy list subsumed under subsuming policy? algorithm returns Subsumed when executed upon policy list and embedding policy, return Allowed.

  4. Return Blocked.

3.2. Is policy list subsumed under subsuming policy?

Given a list of policy objects (policy list), this algorithm returns Subsumed if that list enforces a policy which is an exact match for a given policy object (subsuming policy). It returns Not Subsumed otherwise.

Note: Ideally, we’ll someday define a real subsumption algorithm which would verify that the policy default-src 'none'; script-src https://example.com is subsumbed under default-src *.example.com (as there is no case in which the latter will block a request that the former would allow). That calculation turns out to be hard, so the current algorithm takes the significantly simpler approach of requiring an exact match.

Note: This is not an efficient algorithm. Implementers are encouraged to implement something a little smarter and faster, with the same behavior.

  1. If subsuming policy is null, return Subsumed.

  2. For each policy in policy list:

    1. If policy’s disposition is not Enforce, set skip to the next policy.

    2. If policy’s directive set is not the same size as subsuming policy’s directive set, skip to the next policy.

    3. For each directive in policy’s directive set:

      1. Let subsuming directive be the directive in subsuming policy’s directive set whose name matches directive’s name, or null if no such directive is present.

      2. If subsuming directive is null, skip to the next policy.

      3. If subsuming directive’s value list is not the same size as directive’s value list, skip to the next policy.

      4. For each token in directive’s value:

        1. If token is not present in subsuming directive’s value, skip to the next policy.

    4. Return Subsumed.

  3. Return Not Subsumed.

4. Security Considerations

Embedded documents should be careful to evaluate the proposed Content Security Policy, and not simply to reflect whatever policy an embedder suggests. Doing so may enable a clever attacker to selectively disable pieces of a website’s code which are essential for its own protection.

In particular, documents which do not expect to be embedded should continue to respond to any such request with a Content Security Policy containing an appropriate frame-ancestors directive.

5. Privacy Considerations

This feature allows an embedder to send information to a third-party endpoint via the Embedding-CSP HTTP header. This doesn’t seem to expose any information that couldn’t be tunneled in the HTTP request itself (via GET parameters, etc), and embedders remain in control over the endpoints to which such requests may be made by enforcing a Content Security Policy with an appropriate child-src directive.

6. IANA Considerations

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

6.1. Embedding-CSP

Header field name
Embedding-CSP
Applicable protocol
http
Status
standard
Author/Change controller
W3C
Specification document
This specification (See §2.2 The Embedding-CSP HTTP Request Header)

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

[CSP]
Brandon Sterne; Adam Barth. Content Security Policy 1.0. 19 February 2015. NOTE. URL: http://www.w3.org/TR/CSP1/
[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/
[DOM-LS]
Document Object Model URL: https://dom.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
[RFC5234]
D. Crocker, Ed.; P. Overell. Augmented BNF for Syntax Specifications: ABNF. January 2008. Internet Standard. URL: https://tools.ietf.org/html/rfc5234

IDL Index

partial interface HTMLIFrameElement {
  attribute DOMString csp;
};

Issues Index

Monkey-patching HTML.
Step ~15 of the navigate algorithm needs to be adjusted to add an Embedding-CSP header to a navigational request iff the navigation targets a nested browsing context, and if the browsing context container is an iframe element with a csp attribute. This should be pretty straightforward once the algorithm is rewritten in terms of Fetch, but is a bit tricky today.