I’d never thought of this before. If your site has an XSS flaw and you’ve got a third-party CDN in your CSP, a potential attacker could inject their own code into your site and load in outdated versions of libraries via the CDN to introduce even more vulnerabilities!
What’s particuarly interesting is the suggestion to specify paths in the CSP, which I didn’t know was possible. MDN’s Content Security Policy examples don’t show that being used, only domain names (like
script-src awmb.uk) and subdomain wildcards (like
script-src *.awmb.uk). It is, however, mentioned on the CSP header reference page.
We can also do a simple test ourselves. Here’s a page which loads in multiple versions of jQuery, because who cares about speed and performance?
First up, loading the page with no CSP loads all 3 libraries, as expected:
Next, let’s add the CSP
default-src 'none'; script-src cdnjs.cloudflare.com, which should get us down to two versions.
All good so far, jQueryLand is gradually losing its appeal and is down two 2 copies of the library. I believe the repeated errors are due to CORS, but I’m not 100% sure and perhaps that’s an adventure for another post. Finally, let’s try a CSP with a path:
default-src 'none'; script-src cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/.
Now we’re loading in jQuery from a speedy CDN and have restricted it to a version we know and trust1. Nifty! (Although, jQueryLand really isn’t living up to the name any more.)
Of course, the (arguably) easier option here would be to just self-host your own files, where you can also have the benefits of automatically removing unused code as part of your build process (which is what I do on this site). There are definitely situations though where a big CDN like this makes sense – maybe you can’t manage your own CDN for some reason, or you’re developing something where it’d make the build system too cumbersome, or perhaps you’re CodePen and need a stock of libraries to offer up to your users.
But hey, today I learned you can put paths in CSPs, and I’m sure that’ll come in useful one day.
We mostly know and trust it. It’d be a good idea to use the
integrityattribute in the
<script>tag to ensure the script at that path is actually the script we want. cdnjs will provide you with the hash you need if you copy the
<script>tag using their magic button. I omitted it here to make the code exerpt prettier. ⤶ Back