Chrome (111), FireFox (111), and MS Edge (111) all behave the same way. My (abbreviated for clarity) CSP header includes:
content-security-policy: default-src 'self';script-src 'self' blob: *.usercentrics.eu;connect-src 'self' *.usercentrics.eu;font-src 'self' data: ;img-src 'self' blob: data: *.usercentrics.eu;style-src 'self' 'unsafe-inline' ;frame-src 'self' ;object-src 'none';base-uri 'self';block-all-mixed-content;form-action 'self';frame-ancestors 'self';script-src-attr 'none';upgrade-insecure-requests
When loading the page, the "Issues" tab in DevTools reports "Content Security Policy of your site blocks the use of ‘eval’ in JavaScript" for the 3rd-party script https://app.usercentrics.eu/browser-ui/latest/bundle.js.
However, when I look at the Network tab, I see that this script loaded and apparently ran just fine?!
If I examine the script, it does have an unsafe new Function() string expression.
This makes me wonder:
- How did this script with what’s identified as an unsafe eval still load given that script-src ‘unsafe-eval’ is NOT allowed?
- Is there a "hole" in how CSP headers are evaluated that would allow it to be bypassed and "eval()" functions maliciously inserted and run?
2
Answers
As @Bergi pointed out, the browser still loads and runs scripts (assuming the script-src header allows the src) even if it contains an unsafe eval. However, the script will throw an exception when encountering any unsafe eval expressions when running, unless also specifying 'unsafe-eval' in the script-src directive, which is exactly what I'm trying to avoid.
The browser can’t know that a script contains elements violating the eval policy until it has been loaded. It needs to load and verify it.
Your options are to add ‘unsafe-eval’ to script-src (not recommended), rewrite the offending functions eval/new Function/setInterval/setTimeout as described in https://web.dev/csp/#eval_too, or to stop using/replace the offending script.