Here is the question/problem, I provide a JavaScript from our business domain (e.g. www.mysite.com/js/metrics.js) which is included in over 20 different web apps and include in the head of their documents. It is for analytics tracking. I'm assuming that I need to set a CSP by updating the DOM with a script-src meta tag which only applies to my code and the external JavaScripts it calls (from Akamai CDN assets.adobedtm.com), not the whole web app. Is it possible to do or will my CSP meta tag apply to any external scripts the web app loads and I'd have to know every external JavaScript all the web apps load? Is there any way to achieve this? Any ideas? This is my first time doing CSP so maybe I'm not understanding it correctly... so be gentle!
Thanks!
Yes, your CSP meta tag will apply to any external scripts the web app loads and in common you have to know every external JavaScript all the web apps load.
But if all scripts you load are from assets.adobedtm.com you can just add this source to the script-src directive:
script-src assets.adobedtm.com
and all external scripts from it will be allowed.
Also CSP provides a possibility to do what you want - the 'strict-dinamic' token paired with 'nonce-value' or 'hash-value'. But Safari still does not implemented this (it support by Chrome, Edge and Firefox). If you have CSP with 'nonce-value' like:
script-src 'nonce-SomeSecureValue' 'strict-dinamic';
than:
<script src='https://domain/script.js' nonce='SomeSecureValue'>
will be allowed to load and any its child scripts it inserts will be allowed too.
In case CSP with 'hash-value':
script-src 'sha256-HashOfScriptAllowed' 'sha256-HashOfScript2Allowed' 'strict-dinamic';
than:
<script src='https://domain/script.js' integrity='sha256-HashOfScriptAllowed'>
will be allowed to load and any its child scripts it inserts will be allowed too. But Firefox has a bug and does support 'hash-value' for inline scripts only, not for external.
Alternatively you can use inline <script nonce='SomeSecureValue'> dynamically create script tags and load external scripts</script> and allow it via nonce or hash. All its child scripts will be allowed.
The Safari's 'strict-dynamic' bug can be bypassed using Google's strict CSP.
Related
As far as I understand, there are two ways to specify the Content Security Policy:
On a server side via headers:
res.setHeader("content security-policy", "default-src: 'none';")
In an HTML-page via meta-tag:
<meta content = "default-src 'none';" http-equiv = "Content-Security-Policy" />
My questions:
What is the difference between these two techniques?
Is it enough to use just one of them?
Which one should I use? Backend, frontend, or both?
P.S. Thanks to How does Content Security Policy (CSP) work?, I know what is the CSP and how does it work. What I want to know, however, is where exactly it is better to set the CSP.
Delivering CSP via HTTP header is a preferred way.
Meta tag has the same functionality but for technical reasons it does not support some directives: frame-ancestors, report-uri, report-to and sandbox. Also the Content-Security-Policy-Report-Only is not supported in meta tag.
In SPA (Single Page Application), a meta tag is traditionally used for CSP delivery, because a lot of hostings do now allow to manage of HTTP header.
When SSR (Server Side Rendering), an HTTP header is used more often.
You can use any technically convenient CSP delivery method (keeping in mind the limitations of the meta tag), but do not use both at the same time. Both policies will be executed one after the other, so in case of differences, a stricter one will apply actually.
Note that:
CSP meta tag should be placed in <head>, otherwise it will not work.
Changing the meta tag by javascript will result in both the old and the new policies being in effect.
in cases of CSP for non-HTML files, the meta tag can not be used technically
I am trying to load some css and scripts via some CDNs to improve loading times but I am getting a content security policy issue, but after a fair amount of time reading up on it and trying out different polices it is still giving my the same error.
Currently my policy looks like this -
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https://code.jquery.com/ https://cdnjs.cloudflare.com/ https://maxcdn.bootstrapcdn.com/">
which from my understanding should mean I can load anything from the site itself and the 3 URLs E.G for maxcdn I should be able to load https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js
I did try the very simple and not to be used policy of
<meta http-equiv="Content-Security-Policy" content="default-src *">
but that didn't change anything.
The error I'm getting is -
Refused to load the script 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
The script its trying to load (I will do fall backs after i get this working)-
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
I have tested in chrome (55.0.2883.87) and Edge.
From the error message its as if its not taking my policy but using the default policy set by the browser?
Any help would be much appreciated :)
The script loads without a problem when I test it with a CSP provided by the meta tag you included in your question.
I was able to reproduce the problem by including a conflicting CSP using an HTTP header.
A real HTTP header will trump a meta tag.
You need to make the changes to your server side code or HTTP server configuration instead of to the document.
I had a similar problem due to... an ad blocker (uBlock Origin)
I have been having problems with scripts not getting loaded because of problems with content security policy settings and was wondering if there was a way to set a content security policy so that it lets all websites be accessible for downloading scripts?
If you're not sure exactly what Content Security Policy you need, it's fine to start with a policy that's very permissive, (which is at least better than no policy at all) and refine it.
For example,
Content-Security-Policy: default-src 'self'; script-src *
would allow you to include scripts from anywhere, but everything else, for example images, only from your own site.
I would also recommend you start with Content-Security-Policy-Report-Only, which reports errors but doesn't block the content. That way you can safely test and refine your policy before you enforce it.
See for example Scott Helme's blog article
https://scotthelme.co.uk/content-security-policy-an-introduction/
I have a bookmarklet which uses jQuery and parses some elements on the page. To use jQuery, i am creating a script tag(with src as the jQuery URL) dynamically and appending to the head tag. This works well for many sites. But, there are few sites like Facebook, for which the bookmarklet is not able to inject the external JS file into the dom.I came to know that this behaviour is because of the response header "Content Security Policy" which prohibits the inclusion of scripts from any other unauthorized domain. This is to prohibit XSS atacks.
I have a genuine case to insert an external JS file into the DOM. Is there any workaround to by pass the Content Security Policy?
Self-contained bookmarklets are another possibility. Here's jQuery 3.3.1.
Take
javascript:(function(){
})();
And fill the empty line with the jQuery source code, for example the contents of https://code.jquery.com/jquery-3.4.1.min.js .
Afterward set it as URL of your bookmark(let).
The spec says (at least I think it still does) that CSP should not prevent bookmarklets, but no browser has implemented this. Your only option is to disable CSP in the browser or use an extension.
As a web developer, is there any way to prevent a user's Chrome extensions from being applied to my site? i.e. a header, meta tag, anything? Additionally, if there is, is there also a way to whitelist particular extensions?
It's not possible. At the web server end, you are only only able to control what the browser will allow you to control. In simple terms, this means you can control the data (HTML, javascript, headers etc) that you send back to it. That's about it.
Can't you create a Content Security Policy (CSP) and block inline javascript and only allow javascript from specific domains? You could even create a CSP in report-only mode and collect violation reports via something like https://report-uri.io/