15

Is anyone here able to clarify how caching affects adding a nonce=value to all inline javascript?

If the nonce must be unique and unpredictable, then one would need to disable all server-side (i.e. Varnish, Cloudfront, etc) caching on the pages that use <script nonce="XXXXX">. Correct?

See example 4 here for details.

5 Answers 5

3

If the nonce must be unique and unpredictable, then one would need to disable all server-side (i.e. Varnish, Cloudfront, etc) caching on the pages that use <script nonce="XXXXX">. Correct?

Yes. You always have to disable caching on anything that is dynamically generated (i.e. comes from a script). Since you can't serve unique and unpredictable random values statically, it must be done from a script.

5
  • Thanks. That's the conclusion I came to as well, which makes this method impractical IMHO for all but the smallest sites. Commented Dec 4, 2016 at 7:51
  • @user2687991 Site size has little to do with it. If you have the money, you can always add more servers to handle the load. Commented Dec 4, 2016 at 19:53
  • 3
    Couldn't you use or create a Varnish module that replaces a placeholder string with a nonce in every response?
    – glen-84
    Commented Apr 24, 2017 at 20:59
  • @darkangel what keeps the attacker from including the placeholder? I don't think this is trivial to solve.
    – Prinzhorn
    Commented Jul 12, 2017 at 16:55
  • @Prinzhorn How would the attacker know what the placeholder string is? It could be absolutely anything, and could be updated frequently.
    – glen-84
    Commented Aug 27, 2017 at 13:03
3

This can be happily cached by the application server for days without negatively impacting the CSP nonce protection.

No. The nonce should be unique for every request (nonce = number used once).

I guess the only solution is to use non-cached SSI (server side includes) for the script-tags containing the nonce and combinating that with the nonce in the response content security header or another little SSI for the meta http-equiv="Content-Security-Policy"-tag.

This will make every page unique and thus not cacheable.

2
  • Please add this as a comment to security.stackexchange.com/a/162523/173376 and not a response to the question. I was really confused at first.
    – neuquen
    Commented Mar 12, 2020 at 18:56
  • This is indeed just a comment and, with all respect, not even considering the strategy described there, which is (in short) caching the HTML with a placeholder and then replacing with a nonce value before serving it to the client, so it would be unique for each request.
    – Nick
    Commented Jan 27, 2021 at 11:20
1

It depends which server-side cache we're talking about as this has usually many layers. If your application server is caching HTML to save on expensive SQL queries and template processing, then you still can use nonces by modifying the output HTML on the way back. Your templates and in result the generated HTML may contain placeholders like this:

<script nonce="CSP_NONCE_PLACEHOLDER">
...
</script>

This can be happily cached by the application server for days without negatively impacting the CSP nonce protection.

The nonce is then generated dynamically on the web server and replaces the above placeholder without expiring the cached value:

<script nonce="ee4183bb7784017e0ab7d38ab7ef9eb3a75190e0e76ca5daba8cd20104bd8131">
...
</script>

I have been doing it for years on webcookies.org with the web application running on Django, caching in Redis and web server being Nginx. With the latter there are two options:

    sub_filter_once off;
    sub_filter CSP_NONCE_PLACEHOLDER $ssl_session_id;
2
  • 3
    Now the attacker can simply include REPLACE_WITH_NONCE as part of the exploit, right? The malicious script now gets the valid nonce as well.
    – Prinzhorn
    Commented Jul 12, 2017 at 16:54
  • 1
    right, but the "REPLACE_WITH_NONCE" is example string it can be more complex so more difficult to discover @Prinzhorn Commented Mar 10, 2020 at 22:39
0

Based on the other answers provided here and everything I can find online, the simple answer is that you cannot use nonce and cache. People have created workarounds, but all of them forfeit some amount of confidence that the nonce is doing its job.

0

Caching and CSP nonce can be used together in some cases. It depends on these factors:

  1. when and where you generate and place the nonce
  2. when and where you cache the response

Nonce generation can be done in:

  1. Web server like nginx or apache
  2. application server like Django, Node.js, Tomcat etc

Caching can be done at different levels:

  1. Proxy server caching (Apache/nginx)
  2. application server caching like Django, Node.js, Tomcat etc

All you need is nonce generation and placing in response should be done after caching.

If you cache in application server, you can generate and place nonce in Web server. (nginx hints: set_secure_random_alphanum to generate nonce and sub_filter to replace nonce place holder in response from application server. Setting up nonce generation in nginx)

Another option is to cache only the expensive part of response (not the whole page or response) in application server and generate nonce in application server itself after fetching from cache

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .