Search code examples
content-security-policy

Does order of CSP directives matter?


The default-src has a special behavior as you can imagine it as a "fallback" or "alias" for other directives (such as script-src, style-src etc.).

At https://www.w3.org/TR/CSP3/#example-fae89c48 it is also mentioned that there is a certain "overwrite" behavior, if default-src and one of its counterparts (e.g. script-src) are mentioned in the same CSP header.

But what about order of the directives?

As an example: Is

Content-Security-Policy: default-src 'self'; script-src-elem https://example.com

semantically the same as

Content-Security-Policy: script-src-elem https://example.com; default-src 'self'

? Does now script-src-elem: 'self' apply or script-src-elem: https://example.com? I.e. is the string parsed from left to right or do we have "precedence by CSP directive name"?


Solution

  • https://www.w3.org/TR/CSP3/#framework-directives states that a policy is an ordered set of directives. This could suggest that order matters. However, the standard provides the statement that

    For example: if the effective directive name is worker-src (meaning that we are currently checking a worker request), a default-src directive should not execute if a worker-src or script-src directive exists.

    at https://www.w3.org/TR/CSP3/#should-directive-execute (emphasis provided by the author of this answer). This can be read that default-src shall be ignored completely (independent of its position in a serialized-policy), if a more specific CSP directive is provided.

    A brief test also shows that contemporary browsers behave like this. Let's have an html file with the following content:

    <img src="https://example.com/test.webp">
    <br/>
    <img src="test.webp">
    

    This file is streamed by a webserver, which will add the following header to the html file's request:

    • Variant A: Content-Security-Policy: default-src 'self'; img-src https://example.com
    • Variant B: Content-Security-Policy: img-src https://example.com; default-src 'self'

    The client (in my case a Firefox 121.0 (64-bit)) shows the same behavior for both variants: The first image (hosted on origin https://example.com) is shown, whilst the loading of the second (hosted on 'self') is reported by the network tracer to be prohibited by CSP.

    tl&dr;

    Although CSP's specification defines a policy to be an ordered list, the order of default-src and img-src do not matter. It is assumed that this is the same for all other directive names for which default-src is defined as fallback.

    Hence the evaluation is based on "precedence by CSP directive name".