Personal tools

Security/CSP/Spec

From MozillaWiki

< Security | CSP
Revision as of 10:54, 11 March 2009 by Sidstamm (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents

Specification

The purpose of this document is to provide a detailed description of how Content Security Policy definitions can be deployed. It explains the syntax for creating a CSP policy definition and how the defined policies are received and enforced by a user agent.

Background

Content Security Policy is intended to help web designers or server administrators specify how content interacts on their web sites. It helps mitigate and detect types of attacks such as XSS and data injection. CSP is not intended to be a main line of defense, but rather one of the many layers of security that can be employed to help secure a web site. More information about the intended use of CSP is available in the Overview section.

TODO: It is straightforward to convert a web site into one that can support CSP without loss of functionality. For more information, see Converting Your Site to CSP.

Terminology

A policy is composed of directives (such as "allow: none". Each directive is composed of a directive name and a directive value, which is either a list of host items or a URI (depending on the type of directive).

When CSP is activated for a site, a few refinements to the browser environment are made no matter the policy to help provide proper enforcement of any policy defined. These refinements provide general security enhancements by placing restrictions on the types of dynamic content that is allowed: generally any script on a site that converts text into code (through the use of eval() or similar functions) is disallowed. Details of the refinements can be found in the Refinements section.

Activation and Enforcement

CSP is activated by a client's browser when the X-Content-Security-Policy HTTP header is provided in a HTTP response (or when an equivalent meta tag is defined in the HTML document).

The Content Security Policy to be enforced can be delivered to the browser in one of two ways: directly as the value in the X-Content-Security-Policy HTTP header or a file served from the same host as the resource to be secured. The X-Content-Security-Policy header must either contain a policy definition or a policy-uri field; if both are present, the browser will raise a CSP console error and enforce the most restrictive ("allow none") policy.

If multiple X-Content-Security-Policy headers are present in the HTTP response, then the first one encountered is used and the rest are discarded.

The syntax is identical between file-based and header-based policy. The contents of a policy file are equivalent to the value of the X-Content-Security-Policy header. Authors who are unable to support signaling via HTTP headers can use <meta> tags with http-equiv="X-Content-Security-Policy" to define their policies.

Policy Refinements with a META Tag

When both a X-Content-Security-Policy HTTP header and meta tag are present, the intersection of the two policies is enforced; essentially, the browser enforces the most relaxed policy satisfying both the policies specified in the meta tag and header. The intersection is calculated on a directive-by-directive basis (i.e., the intersection of the allow directive is taken and enforced as the allow part of the effective policy).

For example, the policy in the HTTP header (Pheader) may allow scripts from domains A, B and C. The policy in the meta tag (Pmeta) may allow scripts from domains B, C and D. The policy enforced (Penforced) by the browser will allow scripts from domains B and C only (Penforced = Pheader ∩ Pmeta).

Why Intersect Policies?

TODO: Explain the reasoning behind allowing the policy intersections versus just ignoring one or the other.

Conflicting report-uri values

If both the HTTP header and meta tags define policies with report-uri values, a single report is sent to each of the provided URIs. If both report-uri values are the same, only one report for each violation is sent. If they are different, one report is sent to each unique URI.

TODO: Mention how the two-URI situation is useful for IT/dev reporting

TODO: discuss whether or not this might open up new vectors for data leak through cross-domain reporting. Should we take a similar approach as we do for policy-uri?

Policy Refinement Procedure

When a header and meta tag both present conflicting policies, they are resolved through a straightforward process: first the policies are made explicit (see below), then they are intersected, and the resulting policy is enforced. Through this process, the enforced policy will never be more lenient than either of the conflicting policies.

Policy Refinement Overview

This refinement procedure is only followed if there is a policy present in a HTTP header and there is one present in a META tag.

Making a Policy Explicit

The CSP policy language allows implicit values for directives through use of the "allow" (default) policy directive. To make a policy explicit, the policy language is "expanded", or any missing directives are added with the value specified in the "allow" directive. Once this expansion is complete, the allow directive is no longer necessary, and can be removed. In this way, an expanded policy never has the "allow" directive, but a declared (unexpanded) policy always has the "allow" directive.

Making a policy explicit

Intersecting Policies

The core of combining two policies is essentially the creation of a new policy where any valid request will also satisfy both original policies. In essence, if one HTTP request is allowed by both the Header-specified and Meta-Tag-specified policies, it will be allowed by the refined policy. If an HTTP request is disallowed by either specified policy it will be rejected by the refined policy.

Intersecting two explicit CSPs

In order to determine the intersection of two policies, the different directives are considered individually: for each directive in CSP, the values in both specified policies (A and B) are considered, and only those hosts allowed in both directive values are included in the intersection.

In order to determine the intersection of two policies, the different directives are considered individually: for each directive in CSP, the values in both specified policies (A and B) are considered, and only those hosts allowed in both directive values are included in the intersection.

Intersecting two directives


Policy Language and Syntax

A policy is composed of directives with their corresponding values. Any number of directives can be defined, but the allow directive must always be present. Each directive is followed with a list of host expressions except for policy-uri and report-uri which contain a single URI value. NOTE: In the case of policy refinemens as described above, it is possible to have two report-uri values; in this situation, a copy of the report is sent to each of the two URIs.

Directives

directive description
allow The catch-all section that defines the security policy for all types of content which are not called out in any of the other directives. This specifies the default for un-specified directives.
img-src Indicates which hosts are valid sources for images. Images whose origin doesn't match this directive will not be requested.
script-src Indicates which hosts are valid sources for JavaScript. Only scripts loaded via the src= attribute will be loaded, and the src attribute's value must be indicated by this script-src directive.
object-src Indicates which hosts are valid for object, embed, and applet elements.
frame-src Indicates which hosts are valid for frame and iframe elements.
frame-ancestors Indicates which hosts are valid ancestors for embedding the protected resource via frame and iframe tags. All web pages that are ancestors of the protected content must be indicated by the value of this directive. For example, if A embeds B which embeds C, and C defines a frame-ancestors as "B,C" then C is not rendered as a subframe.
report-uri Instructs the browser where to send a report when CSP is violated. The report will be an XML document sent via POST to the specified URI contained in the value of this directive. Details are found in the <a href="#s_violation_report_syntax">CSP Violation Report Syntax</a> section.
policy-uri Indicates the location of a file containing the security policies for the protected resource. policy-uri should only be defined in the absence of other policy definitions in the X-Content-Security-PolicyHTTP header. If policy-uri is defined among other directives in the header, a console error is raised and the policy enforced by CSP is the most restrictive policy: "allow none".

Host Expression List

Host expressions are a domain host name string that may contain wildcards. Examples of host expressions are "*.mozilla.com" and "mozilla.org". Internationalized domain names are specified according to their punycode representations.


Valid Host Expression Keywords

In place of host name expressions, these keywords can be used to specify classes of sources.

  • self - Refers to the host serving the protected content
  • none - Refers to the empty set (no hosts are valid)
  • data - Specifies data: URIs as valid resources
  • * - Refers to all sources (including data: URIs)

Formal Policy Syntax

<policy>            ::= <allow-directive> (";" <directive> )*

<allow-directive>   ::= allow <host-expr-list>

<directive>         ::= <host-directive> <host-expr-list>
                      | <uri-directive> <RFC 2396 URI>

<host-directive>    ::= "img-src"
                      | "script-src"
                      | "object-src"
                      | "frame-src"
                      | "frame-ancestors"

<uri-directive>     ::= "report-uri"
                      | "policy-uri"

<host-expr-list>    ::= <host-name-expr>
                      | "self"
                      | "none"
                      | "data"

<host-name-expr>    ::= "*"
                      | <host-name-expr>"."<host-name-expr>
                      | <LDH symbol>

Sample Policy Definitions

TODO


Violation Report Syntax

CSP supports a reporting mechanism that allows browsers to notify content providers when their policy is violated. When a report-uri is provided and a policy is violated, information about the protected resource and the violating content is transmitted to the report-uri. Such a report is an XML document containing the following fields:

  • request - HTTP request line of the resource whose policy is violated (including method, resource, path, HTTP version)
  • request-headers - HTTP request headers sent with the request (above) for the CSP-Protected content
  • blocked-uri - URI of the resource that was blocked from loading due to a violation in policy
  • violated-directive - The policy section that was violated (e.g., "script-src *.mozilla.org").

NOTE: in the case where a protected resource is not rendered because the frame-ancestors directive was violated, blocked-uri is not sent and is assumed to be the same as the request URI. The reason for this is because this situation is different from other policy violations: no third-party content was blocked, rather the protected content elected not to load since it does not trust the sites that have enframed it.

TODO: create formal schema for the reports

Violation Report Sample

In this example, a page located at http://example.com/index.html was requested using HTTP 1.1 via the GET method. It provided a policy that included the directive "img-src self", which was violated by a request for some_image.png. The sample XML data sent to the policy-specified report-uri follows.

<csp-report>
  <request>GET /index.html HTTP/1.1</request>
  <request-headers>Host: example.com
           User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0
           Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  </request-headers>
  <blocked-uri>some_image.png</blocked-uri>
  <violated-directive>img-src self</violated-directive>
</csp-report>