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
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 advertisement server parses this request header, decides that it’s acceptable, and reflects it in the response:
HTTP/1.1 200 OK ... Content-Security-Policy: script-src https://trusted-cdn.example.com/
Since the policy asserted by the response matches the policy required by the request, the frame loads successfully.
Embedding-CSP
header:
GET / HTTP/1.1 Host: advertisements-r-us.example.com ... Embedding-CSP: script-src https://trusted-cdn.example.com/ ...
The advertisement server parses this request header, decides that it’s acceptable, and reflects it in the response, along with a policy that prevents plugin loading:
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. The user
agent verifies that one of the policies delivered with the response matches
the requirement, and since additional policies can only make the effective policy for the page more restrictive, allows the frame
to load successfully.
2. Framework
2.1. Integration with HTML
-
iframe
elements have a csp attribute which specifies the policy that an embedded document must agree to enforce upon itself. Valid attribute values match the serialized-policy grammar from [CSP3].partial interface HTMLIFrameElement { attribute DOMString csp; };
HTMLIFrameElement
'scsp
IDL attribute reflects the value of the element’scsp
content attribute. -
A browsing context has a required CSP, which is either
null
or a serialized CSP. For a given browsing context (context), the value is the result of executing §3.3 Obtain the required CSP for context. on context. -
Add the following to the list of error conditions in step 1 of HTML’s process a navigate response algorithm:
-
The §3.1 Is response blocked by context’s required CSP? algorithm returns "
Blocked
" when executed uponresponse
andbrowsingContext
.
Upstream this to WHATWG’s HTML.
W3C’s HTML is not based on Fetch, and does not have a process a navigate response algorithm into which to hook. <https://github.com/w3c/html/issues/584>
-
-
Add the following after step 5 of HTML’s process a navigate fetch algorithm:
-
If
browsingContext
's required CSP is notnull
, append a header whose name is "Embedding-CSP
" and whose value isbrowsingContext
's required CSP torequest
's header list.
Upstream this to WHATWG’s HTML.
W3C’s HTML is not based on Fetch, and does not have a process a navigate fetch algorithm into which to hook. <https://github.com/w3c/html/issues/584>
-
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.
Servers MUST process only the first policy in the first such header received.
3. Algorithms
3.1. Is response blocked by context’s required CSP?
Given a response (response) and a browsing context (context), this algorithm returns "Allowed
" or "Blocked
" as
appropriate:
-
Return "
Allowed
" if either of the following is true:-
context is not a nested browsing context.
-
context’s required CSP is
null
.
-
-
Let embedding policy be the result of executing Content Security Policy Level 3 §parse-serialized-policy on context’s required CSP and "
enforce
". -
If response’s url’s scheme is a local scheme, or if response’s url’s origin is the same as the origin of the
Document
through which context is nested:-
Append embedding policy to response’s CSP list.
-
Return "
Allowed
".
Note: The embedder has direct access to same-origin responses, so if it wishes to enforce a policy on that same-origin response, we simply do so. Likewise, local scheme responses already inherit their policy from the embedder, so we allow the embedder to tighten that policy via this embedding mechanism.
-
-
Assert: context is a nested browsing context, and response is a cross-origin, network schemed resource.
-
If the §3.2 Is policy list subsumed under subsuming policy? algorithm returns "
Subsumed
" when executed upon response’s CSP list and embedding policy, return "Allowed
". -
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.
-
If subsuming policy is
null
, return "Subsumed
". -
For each policy in policy list:
-
If policy’s disposition is not "
enforce
", set skip to the next policy. -
If policy’s directive set is not the same size as subsuming policy’s directive set, skip to the next policy.
-
For each directive in policy’s directive set:
-
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. -
If subsuming directive is
null
, skip to the next policy. -
If subsuming directive’s value list is not the same size as directive’s value list, skip to the next policy.
-
For each token in directive’s value:
-
If token is not present in subsuming directive’s value, skip to the next policy.
-
-
-
Return "
Subsumed
".
-
-
Return "
Not Subsumed
".
3.3. Obtain the required CSP for context.
Given a browsing context (context), the following algorithm returns its required CSP:
-
If context is a nested browsing context.
-
If context’s browsing context container has an
csp
content attribute, return its value.
-
-
Return
null
.
4. Security and Privacy Considerations
4.1. Policy Enforcement
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.
4.2. Policy Leakage
The enforcement mechanism allows a malicious embedder to read a page’s policy cross-origin by brute-forcing its constraints. This could leak interesting data about the page or the user loading the page if the policy contains secret tokens or usernames.
Again, the best defense here is to control the contexts allowed to embed a
given resource via an appropriate frame-ancestors
directive.
4.3. Data Exfiltration
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.
5. IANA Considerations
The permanent message header field registry should be updated
with the following registration for the Embedding-CSP
header: [RFC3864]
-
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)