Personal tools

Security/CSP/Specification

From MozillaWiki

< Security | CSP
Revision as of 10:19, 14 June 2010 by Sidstamm (Talk | contribs)

Jump to: navigation, search

Contents

Specification

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 goals section of the overview document.

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.

Definitions

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, for certain types of directives.

When CSP is activated for a site, a few base restrictions in the browser environment are enforced by default to help provide proper enforcement of any policy defined. These base restrictions provide general security enhancements by limiting 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 Base Restrictions section.

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, or CSP will revert to enforcing the policy allow 'none' for the protected content. Each directive is followed with a list of host expressions except for policy-uri and report-uri which contain a single URI value. Some example policy sets are provided below.

Note: In the case of policy refinements 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.


Sample Policy Definitions

Example 1: Site wants all content to come from its own domain:

X-Content-Security-Policy: allow 'self'

Example 2: Auction site wants to allow images from anywhere, plugin content from a list of trusted media providers (including a content distribution network), and scripts only from its server hosting sanitized JavaScript:

X-Content-Security-Policy: allow 'self'; img-src *; \
                           object-src media1.com media2.com *.cdn.com; \
                           script-src trustedscripts.example.com

Example 3: Server administrators want to deny all third-party scripts for the site, and a given project group also wants to disallow media from other sites (header provided by sysadmins and header provided by project group are both present):

X-Content-Security-Policy: allow *; script-src 'self'
X-Content-Security-Policy: allow *; script-src 'self'; media-src 'self';


Example 4: Online payments site wants to ensure that all of the content in its pages is loaded over SSL to prevent attackers from eavesdropping on requests for insecure content:

X-Content-Security-Policy: allow https://*:443

Directives

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. Defines the default policy for un-specified content types, except for frame-ancestors, which MUST be enforced as "*" when not explicitly stated.
  • User Agents MUST NOT load content from any source if the allow directive is not explicitly specified. This can be considered equivalent to the policy "allow 'none'".
  • User Agents MUST enforce this directive for all HTTP requests not subject to one of the more specific directives.
options
  • Options for modifying the underlying behavior of CSP are specified here.
  • The value of this directive is a space-separated list of LDH tokens, each specifying a feature to enable or disable:
    • inline-script enables inline scripts and javascript: URIs
    • eval-script enables the eval() functionality of scripts interpreted by the browser, and allows code to be created from strings in uses of the new Function() constructor, setTimeout and setInterval
  • User Agents must ignore any tokens not recognized by CSP, and SHOULD post a non-fatal warning to the error console.
img-src
  • Indicates which sources are valid for images and favicons.
  • User Agents MUST NOT request images from non-approved sources.
  • User Agents MUST subject image requests to the allow directive if img-src is not explicitly specified.
media-src
  • Indicates which sources are valid for audio and video elements.
  • User Agents MUST NOT request audio and video elements from non-approved sources.
  • User Agents MUST subject audio and video requests to the allow directive if media-src is not explicitly specified.
script-src
  • Indicates which sources are valid for scripts.
  • Regulates which scripts can be loaded via the src= attribute.
  • User Agents MUST NOT request scripts from non-approved sources.
  • User Agents MUST subject script requests to the allow directive if script-src is not explicitly specified.
object-src
  • Indicates which sources are valid for object, embed, and applet elements.
  • User Agents MUST NOT request objects from non-approved sources.
  • User Agents MUST subject object, embed, and applet requests to the allow directive if object-src is not explicitly specified.
frame-src
  • Indicates which sources are valid for frame and iframe elements.
  • User Agents MUST NOT request frame content from non-approved sources.
  • User Agents MUST subject frame requests to the allow directive if frame-src is not explicitly specified.
font-src
  • Indicates which sources are valid for @font-src CSS loads.
  • User Agents MUST NOT request fonts served from non-approved sources when intended for use as a font in CSS.
  • User Agents MUST subject requests caused by @font-src to the allow directive if font-src is not explicitly specified.
xhr-src
  • Indicates which sources are valid for XMLHttpRequest connections.
  • User Agents MUST NOT cause XMLHttpRequests to open requests to sources not permitted by this directive.
  • User Agents MUST subject requests caused by XMLHttpRequest to the allow directive if xhr-src is not explicitly specified.
frame-ancestors
  • Indicates which sources are valid ancestors for embedding the protected resource via object, frame and iframe tags. An ancestor is any HTML document between the protected resource and the top of the window frame tree; for example, if A embeds B which embeds C, both A and B are ancestors of C. If A embeds both B and C, B is not an ancestor of C, but A still is.
  • If this directive is not explicitly stated in the policy, it is assumed to be "*". This is different than the other source directives that inherit the value of allow.
  • 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.
  • Answers the question: "Which sites may embed this resource?"
  • User Agents MUST NOT render the protected document when any of its frame ancestors are not allowed by this directive.
  • User Agents MUST always render the protected document if frame-ancestors is not explicitly specified.
  • Note that this directive addresses the clickjacking threat, but not CSRF
    • Using frame-ancestors, it is possible to prevent a resource from being framed within a malicious webpage. The browser will stop loading the protected document as soon as its frame-ancestors policy is received and a policy violation is determined.
    • However, this directive does not prevent the request for the document from being sent to the framed document's server, as policy directives are received by the browser in the server's response. To mitigate Cross-Site Request Forgery, the Sec-From header provides a more robust mechanism.
style-src
  • Indicates which sources are valid for externally linked stylesheets.
  • User Agents MUST always allow inline stylesheets and style attributes of HTML tags.
  • User Agents MUST NOT request stylesheets from sources not allowed by the style-src directive.
  • User Agents MUST subject stylesheet requests to the allow directive if style-src is not explicitly specified.
report-uri
  • Instructs the browser where to send a report when CSP is violated.
  • The report will be an JSON object with MIME type application/json sent via POST to the specified URI contained in the value of this directive.
  • Acceptable report URIs MUST use the scheme and port as the protected content, and the public suffix and most general DNS label of the protected content and the report URI must match. For example www.foo.co.uk and reports.foo.co.uk, but not reports.bar.co.uk. Relative URIs are acceptable, and are resolved within the same scheme, host and port as the document served with the CSP.
  • User Agents MUST send violation reports to any acceptable URIs in this directive. Details about the information provided in violation reports are found in the Violation Report Syntax section.
  • User Agents MUST ignore report URIs that don't match the public suffix and base host match requirements. User Agents SHOULD log one error to an error console. User Agents MUST then continue CSP enforcement as if the report URI were not specified.
  • User Agents MUST NOT honor HTTP 3xx response codes to prevent HTTP header leakage across domains.
policy-uri
  • Indicates the location of a file containing the security policies for the protected resource.
  • policy-uri MUST only be defined in the absence of other policy definitions in the X-Content-Security-Policy HTTP header.
  • User Agents MUST raise a fatal error and MUST enforce the policy "allow 'none'" if policy-uri is defined among other directives in the header.
  • User Agents MUST ignore any policy URIs of a different origin (scheme, host, or port) from the protected content. User Agents SHOULD resolve relative URIs within the same scheme, host and port as the protected document.

Source Expression List

Source expressions are a combination of scheme and often host and port. Source expressions may contain wildcards. Examples of host-only source expressions are "*.mozilla.com" and "mozilla.org". Internationalized domain names are specified according to their punycode representations.

Source expressions may also specify a scheme and/or port. If the scheme is not specified as part of the source expression, a User Agent MUST use the same scheme as the protected document. If a port is not specified as the source expression, a User Agent MUST use the default port for the source's scheme (whether it is inherited or explicitly specified in the source expression).

When a scheme alone is the entire source expression (e.g., javascript:) a User Agent MUST not enforce host and port restrictions. This is because for some schemes, host and port are irrelevant (e.g., data:).

Host-less Schemes

Valid sources do not always require a host. Schemes such as data can be enabled as a source by stating the name of the scheme followed by a colon. For example:

data:
expresses support for all data URIs.


Port Wildcards

A wildcard "*" token may be used in place of the port number. This indicates that all ports (except banned ports) are valid for the source. Examples:

http://foo.com:*
Any port may be used to access content from foo.com over http
foo.com:*
Any port may be used to access content from foo.com, over the same scheme as the CSP-protected resource

Hostname Wildcards

Each source expression's host name MAY contain up to one wildcard (*) and it MUST be the left-most DNS label.

Valid wildcard host names expressions include "*.mozilla.com" and "*".

Invalid wildcard host name expressions include "www.*.com", "*.mozilla.*" and "mozilla.*".

A wildcard token (*) matches zero or more DNS labels. All of "d.c.b.a", "c.b.a", and "b.a" match the expression "*.b.a".

Source Expression Keywords

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

'none' 
Refers to the empty set (no hosts are valid)
'self' 
Refers to the source serving the protected content -- this is inclusive of scheme, host and port.

Formal Policy Syntax

<policy>            ::= <allow-directive>";"<directive-list>

<allow-directive>   ::= allow <src-dir-value>

<directive-list>    ::= <empty> | <directive>";"<directive-list>

<directive>         ::= <src-directive>" "<src-dir-value>
                      | "options "<options-dir-value>
                      | <uri-directive>" "<URI (RFC 2396)>
                      | <future-directive>" "<future-value>

<future-directive>  ::= <ldh-str>

<future-value>      ::= <empty>
                      | <future-value><fv-char>

<options-dir-value> ::= <empty>
                      | "eval-script" <options-dir-value>
                      | "inline-script" <options-dir-value>
                      | <(unrecognized)ldh-str> <options-dir-value>

<src-directive>     ::= "img-src"
                      | "media-src"
                      | "style-src"
                      | "object-src"
                      | "frame-src"
                      | "font-src"
                      | "script-src"
                      | "xhr-src"
                      | "frame-ancestors"

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

<src-dir-value>     ::= <source-list>
                      | "'none'"

<source-list>       ::= <source>
                      | <source-list>" "<source>

<source>            ::= "'self'"
                      | <scheme><host><port>
 
<scheme>            ::= <empty>
                      | <scheme-name>":"
                      | <scheme-name>":/"
                      | <scheme-name>"://"

<scheme-name>       ::= <alpha><scheme-suffix>

<host>              ::= <empty>
                      | <host-name>

<host-name>         ::= "*" 
                      | <ldh-str>
                      | <host-name>"."<ldh-str>

<port>              ::= <empty>
                      | ":*"
                      | ":"<integer>

<scheme-suffix>     ::= <scheme-chr> 
                      | <scheme-suffix><scheme-chr> 

<ldh-str>           ::= <let-dig-hyp>
                      | <ldh-symbol><let-dig-hyp>

<let-dig-hyp>       ::= <letter> | <digit> | "-"

<scheme-chr>        ::= <letter> | <digit> | "+" | "." | "-"

<fv-char>           ::= <letter> | <digit> 
                       | " " | "+" | "." | "-" | "_"
                       | "'" | """ | "[" | "]" | "\" | "|"
                       | "/" | "?" | "{" | "}" | "=" | "+"
                       | "`" | "~" | "!" | "@" | "#" | "$"
                       | "%" | "^" | "&" | "*" | "(" | ")"
                       
<letter>            ::= "a"|"b"|"c"|"d"|"e"|"f"|"g"|"h"|"i"
                       |"j"|"k"|"l"|"m"|"n"|"o"|"p"|"q"|"r"
                       |"s"|"t"|"u"|"v"|"w"|"x"|"y"|"z" 
                       |"A"|"B"|"C"|"D"|"E"|"F"|"G"|"H"|"I"
                       |"J"|"K"|"L"|"M"|"N"|"O"|"P"|"Q"|"R"
                       |"S"|"T"|"U"|"V"|"W"|"X"|"Y"|"Z"

<integer>           ::= <digit> | <integer><digit> 

<digit>             ::= "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"|"0"

<empty>             ::= ""

Violation Report Syntax

User Agents MUST notify any provided report-uri when its containing policy is violated. These reports contain information about the protected resource and the violating content, and MUST be transmitted to any specified report-uris via HTTP POST if available in the employed scheme, otherwise User Agents MUST choose an appropriate "submit" method. User Agents MUST not honor redirection responses. The report body MUST be a JSON object having the following properties:

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").
original-policy 
The original policy as served in the X-Content-Security-Policy HTTP header (or if there were multiple headers, a comma separated list of the policies)

NOTE: in the case where a protected resource is not rendered because the frame-ancestors directive was violated, User Agents MUST not send blocked-uri (it is assumed to be the same as the request URI).

Violation Report JSON Format:

{
  csp-report: {
    request: "GET /index.html HTTP/1.1",
    request-headers: "Host: example.com
                      User-Agent: ...
                      ...",
    blocked-uri: "...",
    violated-directive: "..."
  }
}

The MIME type of the transmitted report will be set to application/json.

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 http://evil.com/some_image.png. The sample JSON object sent to the policy-specified report-uri follows.

{
  "csp-report":
    {
      "request": "GET http://index.html HTTP/1.1",
      "request-headers": "Host: example.com                                                        
                          User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.3a5pre) Gecko/20100601 Minefield/3.7a5pre                                                        
                          Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8  
                          Accept-Language: en-us,en;q=0.5                                          
                          Accept-Encoding: gzip,deflate                                            
                          Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7                           
                          Keep-Alive: 115                                                          
                          Connection: keep-alive",
      "blocked-uri": "http://evil.com/some_image.png",
      "violated-directive": "img-src 'self'",
      "original-policy": "allow 'none'; img-src *, allow 'self'; img-src 'self'"
    }
}

User Agent Behavior

Base Restrictions

The following restrictions will apply whenever any CSP directives are declared for a document:

No inline scripts will execute

  • User Agents MUST block:
    • The contents of internal <script> nodes
    • javascript: URIs, e.g. <a href="javascript:bad_stuff()"> (unless enabled by policy)
    • Event-handling attributes, e.g. <a onclick="bad_stuff()">

  • User Agents MUST not block:
    • Scripts imported from external files whose sources are allowed by the protected document's policy AND are served with a Content-Type of application/javascript or application/json.

User Agents MUST generate and send a violation report with the violated-directive value set to "Base Restriction Violation: no inline scripts will execute" when this base restriction is violated.

Code will not be created from strings

  • User Agents MUST block:
    • calls to eval()
    • calls to setTimeout using a String argument, e.g. setTimeout("evil string...", 1000)
    • calls to setInterval using a String argument, e.g. setInterval("evil string...", 1000)
    • calls to the Function constructor, e.g. var f = new Function("evil string...")

  • User Agents MUST not block:
    • Functions declared using the function operator, e.g. function f() { some_code }, or var f = function() { some_code }
    • calls to setTimeout using a Function argument, e.g. setTimeout(myFunc, 1000)
    • calls to setInterval using a Function argument, e.g. setInterval(myFunc, 1000)

User Agents must generate and send a violation report with the violated-directive value set to "Base Restriction Violation: no code will be created with strings" when this base restriction is violated.

No data: URIs unless opted-in to via explicit policy

  • User Agents MUST block:
    • data: URIs when used as a source for inline content

  • User Agents MUST not block:
    • data: URIs when used as a source for inline content explicitly allowed by the protected document's policy.

User Agents MUST generate and send a violation report with the fields set appropriately when this base restriction is violated.

XBL bindings must come from chrome: or resource: URIs

NOTE: this is currently Firefox-Specific, but related behavior in other User Agents should also be limited.

  • User Agents MUST block:
    • XBL bindings loaded via any protocol other than chrome: or resource:

  • User Agents MUST not block:
    • XBL bindings loaded via the chrome: or resource: protocols

User Agents MUST generate and send a violation report with the fields set appropriately when this base restriction is violated.

Restrictions on policy-uri and report-uri

User Agents MUST raise a fatal error AND ignore any policy-uri that does not refer to the same origin (scheme/host/port) as the protected document OR that is not served with MIME type set to "text/x-content-security-policy".

User Agents MUST raise a non-fatal warning AND ignore any report-uri directive values that refer to an origin not of the same public suffix AND base host. (For instance, a report-uri in a policy for "www.mysite.com" may refer to anything that ends with "mysite.com".)

  • User Agents MUST raise a fatal error AND revert to the policy "allow 'none'" when:
    • parsing a policy-uri directive value referring to a URI on a different host from the protected document.
    • receiving a policy-uri HTTP response served with Content-Type other than text/x-content-security-policy
  • User Agents MUST raise a non-fatal warning AND ignore:
    • any report-uri directive values that refer to a URI on a different public suffix from the protected document
    • any report-uri directive values that refer to a base host than the protected document

Privacy Consideration: The report sent to the report-uri contains potentially sensitive information, including cookie values and query string parameters. This information is intended only for the protected site for debugging purposes or similar. An attacker should not be allowed to steal the report information by injecting a report-uri, along with an arbitrary policy to be violated.

Activation and Enforcement

User Agents MUST activate CSP and enforce it for a document when the X-Content-Security-Policy HTTP header is provided in its HTTP response. User Agents MUST parse AND begin enforcing the policy before any of the protected content is parsed.

Policy Refinements with Multiple Headers

When multiple instances of the X-Content-Security-Policy HTTP header are present in an HTTP response, the User Agent MUST enforce the intersection of the policies; essentially, the User Agent SHOULD enforce a policy that is more strict than both the policies specified in the multiple headers, but only strict enough to correspond to rules in all policies. Any web request that satisfied all policies alone MUST be accepted by the new policy, but any request rejected by any of of the two policies MUST be rejected by the new policy.

User Agents MUST calculate the intersection 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). Explicitly, for two policies:

define R1 ≡ all URIs accepted by the first HTTP header CSP
define R2 ≡ all URIs accepted by the second HTTP header CSP
Re = {r | r ∈ R1 AND r ∈ R2}
(Re is the set of all URIs accepted by the intersected CSP)

If more than two instances of the X-Content-Security-Policy header are present in the response, the User Agent MUST perform intersection digest-style: the first two policies are removed from the set of headers to digest, intersected, and the result is placed back in the set. This continues until only one policy remains. e.g.,

intersect(A, B, C, D) = intersect(A, intersect(B, intersect(C,D)))

Example: If two policy headers are present, one (P1) may allow scripts from domains A, B and C. The policy in the other header (P2) 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 = P1 ∩ P2).

Conflicting report-uri values

User Agents MUST send a single report to each URI when multiple headers define policies with different report-uri values

Example: Report-duplication (or multiple reporting) is useful in the case where two different groups want to receive reports, but may not share access to the reports archive. Take for instance a large web company that has a separate sysadmin staff (who are also in charge of security at some level) and project teams. One project team may be interested in receiving reports about violations of their CSP, but are not interested in violations on other parts of the web site. The sysadmin team wants to record all violations from all parts of the site into a massive archive. The multiple reporting technique allows both entities to receive the reports they want without causing extra data-mining work on the part of the sysadmin team to isolate the reports that each project team may want.

Data Leak Vectors

Since HTTP headers and the entire request string are sent in the report, it is possible that, in case of compromise, a violation report could leak private information to an arbitrary URI.

To avoid any possible cross-domain cookie or authentication token transfer, User Agents MUST only transmit reports to the same origin (scheme, host, and port) that served the protected content.

Policy Refinement Procedure

User Agents MUST resolve two headers present conflicting policies through the following process:

  1. The policies are made explicit (see below)
  2. They are intersected
  3. The resulting policy is enforced.

Policy Refinement Overview

User Agents MUST follow this refinement procedure when there are multiple instances of the X-Content-Security-Policy HTTP header present in the HTTP response, or multiple policies are present in the HTTP header (separated by commas).

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. This makes it easier to intersect policies and to enforce them, since all directives will have an explicit value.

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 policies in question, 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.


Intersecting two directives

Handling Parse Errors

A number of different problems may be encountered while parsing the CSP policy. These parse errors are not policy violations, and any error messages caused by parse errors are separate from the violation report sites may elect to receive when their site's policies are violated, via the report-uri directive.

User Agents SHOULD report parse errors locally in the user agent's error console.

Unrecognized Directive
If an unrecognized directive (name not recognized) is encountered by a User Agent, the directive and its value are skipped (up to a semicolon or end of header, whichever is first) and the User Agent SHOULD report a warning message to the Error Console stating the unrecognized directive name.
Unrecognized options token
If an unrecognized token is present in the options directive value, the User Agent MUST ignore it and SHOULD report a warning message to the Error Console stating the unrecognized token.
Missing "allow"
If the "allow" directive is not present, the User Agent SHOULD report a warning message to the Error Console and MUST assume the directive value "allow 'none'" for the policy. The User Agent MUST enforce the rest of the policy as written (assuming no other policy errors are encountered).
Directive Syntax Error
When any known directive contains a value that violates CSP syntax, the User Agent SHOULD report a warning message stating the invalid syntax to the Error Console AND MUST "fail closed" by enforcing the most secure policy, "allow 'none'" for the protected document.
No Recognized Directives
If no recognized directives are present in the stated policy, the User Agent SHOULD report a warning message to the Error Console stating "invalid policy" AND MUST enforce the policy "allow 'none'" on the protected document.
Other Parsing Errors
Any other parsing errors not covered here SHOULD cause the User Agent to enforce the policy "allow 'none'". If such a case should arise, the User Agent SHOULD report a descriptive error to the Error Console describing the problem.

Non-Normative Client-Side Considerations

User Scripts 
CSP should not interfere with the operation of user-supplied scripts (such as browser add-ons and bookmarklets).
Redirects to Content 
When a resource is requested from a URI X[0] protected by a policy CSP, that resource's URI is only loaded if permitted by CSP. If the URI X[0] resolves to an HTTP redirect of any kind (temporary or permanent) the new URI X[1] is also required to be permitted by the policy CSP. The effect is that all requests generated by the document must be permitted by the CSP whether they are the initial request or the steps taken during a redirect.
Future Directives 
In order to support future directives (or new versions of this spec), CSP must parse but ignore directives with unknown names. When an unknown directive is encountered by the UA, a warning is posted to the error console, and the directive is ignored.

Report-Only mode

To ease deployment, CSP can be deployed in "report-only" mode where a policy served is not enforced, but any violations are reported to a provided URI. The effect is a "what if" scenario where a site can specify a policy and measure how much breaks. Additionally, a report-only header can be used to test a future revision to a policy without actually deploying it.

Report-only mode is enabled by specifying a policy in the X-Content-Security-Policy-Report-Only header instead of the X-Content-Security-Policy header.

If both a X-Content-Security-Policy-Report-Only header and a X-Content-Security-Policy header are present in the same response, both policies are honored. The policy specified in X-Content-Security-Policy headers is enforced. All loads/scripts are compared the one specified in the X-Content-Security-Policy-Report-Only header, and any violations generate reports but are not enforced.

HTTP Server Behavior

HTTP Header Placement

The X-Content-Security-Policy HTTP Response header MAY be present in the Message Headers section of a server's HTTP response. Specifically, it MUST NOT appear in the Trailer Headers section of the response, so that the policy may be enforced as the rest of the page content loads. Multiple X-Content-Security-Policy Response headers MAY be inserted.