• caglararli@hotmail.com
  • 05386281520

Content security policy for script-src directive

Çağlar Arlı      -    15 Views

Content security policy for script-src directive

I have a web app that is built using Vite for the react front-end part and uses .net API backend. The backend also configures a static file service for the prebuild frontend files but otherwise implements the API that the front-end is heavily using.

The static index.html includes some of the scripts that will add new script tags on demand when the user requests a specific page.

I want to have as strict CSP as possible, so I started off with default-src 'none'. Then I started opening individual directives as I saw fitted the app.

But I'm struggling a bit with script-src, because of the way my app is build/works. These are the steps I took:

  1. Initially I added the script hashes of scripts that are embedded directly in the index.html (like google-related script etc.) but this subsequently failed to load external scripts that are in the index.html but not embedded code wise.
  2. So I calculated the hashes of all prebuild script assets and added them to the CSP header assuming they work in the same way as the embedded scripts (browser loads the source of the script (embedded or external) and calculates its hash and then comparing it to the hash list in the CSP header. but this doesn't work in this way for external scripts.
  3. I had to implement SRI (SubResource Integrity) so I configured my Vite build to inject integrity attributes to all external script tags in the index.html and give them the matching hash value. This started to execute all those external scripts, but it didn't work for the scripts that were added programmatically afterwards during code execution on demand.
  4. So I thought of adding 'strict-dynamic' which would grant dynamically added scripts the same permission as those that define SRI hashes. But then I paused...

I started to doubt whether all this is making my site more vulnerable than simply setting script-src 'self'. If my website is vulnerable to script injection, so that the hacker would be able to inject a script into the data that my app is rendering, wouldn't the app be more vulnerable with 'strict-dynamic' than it is with 'self'. If the script would inject an external script pointing outside of the app's origin (or make a request outside of the origin, which I can control with connect-src 'self'), the 'strict-dynamic' would actually allow the execution of the malicious external script, but 'self' wouldn't.

Question

I'm wondering what good is the strict-dynamic then if it allows permission grant to any dynamic script that is being loaded by a safe script? In which scenario would the strict-dynamic directive value make sense?

Since I don't want to make my backend code more complex than it needs to be I'm trying to avoid using a nonce. But then again, I would end up with the same problem as with SRI. Only the build-time scripts within the index.html would get the nonce, but any dynamic ones wouldn't. So I'd resolve back to either strict-dynamic or self.

Do advise me how to set my script security as tightly as possible or tell me where my thinking goes wrong.

If there's any missing info, do add a comment and I'll try to answer.