Removing 'unsafe-eval' from csp headers - javascript

I am talking in angular context.
If the hash value of every *.js files in index.html are referenced in csp header script-src then, do we still need to remove 'unsafe-eval' for better security?

Related

Why CSP header block jQuery on dev server, but work on localhost?

Hello we try to implement CSP header to our Angular application and I faced a problem with jQuery. CSP blocked jquery because it executes inline script, which is not allowed by my rules, 'unsafe-inline' in script-src not added. But on localhost everything works fine, on dev server not. Why its happend ? And how can I allow to work jquery scripts without 'unsafe-inline'. Script file loaded from same origin not from cdn.
Error:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-eval' 'nonce-11111' https://*.website.com http://cdn.heapanalytics.com". Either the 'unsafe-inline' keyword, a hash ('sha256-wW7QqtXdIoLePBBqZfs1uttj5IW0GdlgNOmzyyPk7Xg='), or a nonce ('nonce-...') is required to enable inline execution.
Code with error:
function b(e, t, n) {
var r, i, o = (n = n || E).createElement("script");
if (o.text = e,
t)
for (r in c)
(i = t[r] || t.getAttribute && t.getAttribute(r)) && o.setAttribute(r, i);
n.head.appendChild(o).parentNode.removeChild(o) // this line
}
CSP rules:
<meta
http-equiv="Content-Security-Policy"
content="
default-src 'self' https://*.website.com https://s3.amazonaws.com/bucket/ https://bucket.s3.amazonaws.com/;
script-src 'self' 'unsafe-eval' 'nonce-11111' https://*.website.com http://cdn.heapanalytics.com;
style-src 'self' 'unsafe-inline' https://*.website.com;
font-src 'self' https://*.website.com;
img-src 'self' https://*.website.com https://s3.amazonaws.com/bucket/ https://heapanalytics.com data:;"
/>
Nonce used for script in root html for analitics. I tried hash, but it's also not work.
It is because .createElement("script") tries to create script (unsafe inline) which doesn't have nonce neither hash. You might be looking for CSP - Strict dynamic which specifies that the trust explicitly given to a script present in the markup, by accompanying it with a nonce or a hash, shall be propagated to all the scripts loaded by that root script. (source: MDN)
You also asked "Why its happend?"
It's very hard to tell what and why a particular call is made without a code sample, but you could find out more information in this question: jQuery 3.1.1 violation of CSP directive

how to add Content Security Policy (CSP)

I want to access a website using javascript. but I am getting the following error in the console.
Refused to connect to 'https://example.com' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
I have added the following meta tag in the index.html,
meta http-equiv="Content-Security-Policy" content="connect-src 'self' http://example.com;" />
Isn't this the right way to add CSP? please help.
You already have one CSP published with the default-src 'self' policy. Quite possible it was done via HTTP header.
Check the Helmet middleware settings in case of NodeJS server, or Header set in the .htaccess file in case on Apache server. In case of Nginx it can be add_header in the config.
By adding <meta> tag you just publish a second CSP, which does not overrides the first one. 2 CSPs works subsequently - all sources should pass both CSP.
Figure out where CSP is publushed and add connect-src 'self' http://example.com; there.

Content-Security-Policy blocks Vue.js

I am serving a HTML page in my node.js server with express.public() function.
and i added this into my html page:
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
And Chrome gaves me a Content-Security-Policy to me.
I used this middlewares in my Node index.js
app.use(morgan('tiny'));
app.use(helmet());
app.use(cors());
app.use(express.json());
app.use(express.static("./public"));
My application headers:
Content-Security-Policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
How can i add this script without any SecurityPolicy
SOLVED
I remove "Helmet" from my project. Helmet is blocking the all cdn and scripts other then absolute domain.
Content Security Policy is set in the html file being served or by the software serving the html (e.g Nginx, Apache).
At the moment you have: default-src 'self', this means you are telling the browser that it is only able to make requests to its own domain.
You need to add https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js to this list of domains it can access.
That would be something like:
Content-Security-Policy: default-src 'self';script-src 'self' https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js; base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
So default-src: self sets the default to restrict requests to only your own domain.
script-src 'self' https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js overrides this and says specifically for scripts restricts request to only your domain and that url.
This has lots of details and examples:
https://content-security-policy.com
In addition to what silent-tiger said, I think you should first find out which middleware is responsible for adding this content policy. Do this by disabling all middleware (except express static) and then add the other middlewares one by one until you see the Content Secutity Policy headers again.
If you found which middleware is responsible, then you know which middleware you should configure.

Understanding connect-src, script-src and style-src when everything is loaded dynamically

I am a little confused with the directives available with Content Security Policy Header. Mainly confused with connect-src , script-src and style-src
I have a javascript, which sends Fetch, Ajax (on the same domain) and dynamically loads a link tag that has a stylesheet.
If I have to get my script whitelisted on a domain, should this be part of all connect-src, script-src and style-src ? I am a little confused here.
To make it clearer, there is a script at https://example.com which loads, sends data from https://example.com and loads stylesheet sitting at https://some-another-domain.com. How should the content security policy reflect this? Should connect-src , script-src and style-src include both the domains?
Could someone help clarify this?
Each directive should contain only sources which it covers (controls).
The connect-src directive covers the URLs from which resources can be loaded using following script API interfaces(see the test):
<a ping='...'>
fetch()
XMLHttpRequest()
sendBeacon()
WebSocket() (hence ws:/wss: scheme can be specified in connect-src/default-src only)
EventSource()
Therefore if you perform XMLHttpRequest('https://example.com/ajax') or use jQuery $ajax('https://example.com/ajax') which internally calls XMLHttpRequest(), you need to allow the https://example.com in the connect-src:
connect-src https://example.com;
Similarly if you use fetch('https://google.com/api/json'), you need to add this host-source to the connect-src:
connect-src https://example.com https://google.com/api/;
and so on for all 6 the APIs above.
The script-src directive controls 5 things:
external scripts loading via <script src='http://example.com/script.js'></script>. You need to allow relevant host-sources in the script-src for that. Alternatively 'nonce-value'/'hash-value' token can be used.
inline script blocks like <script>...</script>. You need to use 'unsafe-inline' or 'nonce-value'/'hash-value' tokens in the script-src to allow such scripts.
eval(), setTimeout(), setInterval(), Function(), setImmediate(), execScript() funct calls are gated on the 'unsafe-eval' source expression. If you use those you need to have 'unsafe-eval' in the script-src (with some exceptions for setTimeout()/setInterval()).
navigation to javascript-URLs like <a href='javascript:...'>.
inline event handlers in tags like <div onblur='...'>, <input onclick='...'>.
* for last 2 things you need to have 'unsafe-inline' in the script-src directive or use unsafe-hashes + 'hash-value' tokens paired (supported with some bugs as for now).
The style-src directive covers several things(see the test):
stylesheet requests via <link href='http://example.com/min/css.css' rel='stylesheet'>. In this case you need to add http://example.com host-source to the style-src directive.
stylesheet requests from the CSS #import url('https://example.com/style_import.css')
stylesheet requests from a Link HTTP response header field Link: https://example.com/file.css; rel=stylesheet.
inline style blocks: <style>...</style>. You need to have 'unsafe-inline' or 'nonce-value'/'hash-value' in the style-src to allow these.
style= attribute in tags: <tag style='color:green; margin:0 auto;'>. You need to have 'unsafe-inline' in the style-src to allow these. Or use paired the 'unsafe-hashes' + 'hash-value' (is not widely supported as for now).
* JS call setAttribute('style', 'display:none;') is considered as <tag style='display:none;'> above.
using of CSSStyleSheet.insertRule(), CSSGroupingRule.insertRule(), CSSStyleDeclaration.cssText and CSSStyleRule.selectorText was intended to be gated to 'unsafe-eval' in the style-src, but it's not implemented yet.
Any usage of the above constructs (even via script calls) requires to allow relevant sources or tokens in the styler-src directive.

CSP: How to allow unsafe-eval for a given URI prefix (Firefox)

I'm trying to use MathJax as part of our web application which uses pretty strict Content Security Policy (CSP). The problem is that MathJax is coded to use eval() [to be exact, in form of Function()] which is not considered safe by default by CSP.
I'm using following CSP header currently:
X-Content-Security-Policy: allow 'self'; img-src *; media-src *; frame-src *; font-src *; frame-ancestors 'none'; style-src *; report-uri '/:save-csp-violation';
Which causes MathJax 2.0 code to fail because it uses Function(). I tried to allow unsafe-eval (i.e. Function()) only for MathJax located within the same origin below path /:static/math/. To do that, I tried to add
unsafe-eval '/:static/math/*'
to make the full header look like
X-Content-Security-Policy: allow 'self'; img-src *; media-src *; frame-src *; font-src *; frame-ancestors 'none'; style-src *; report-uri '/:save-csp-violation'; unsafe-eval '/:static/math/*'
but I still cannot Firefox 13.0 to run the code. I'm getting an error message to Firefox Web Console (located in Tools - Web Developer):
[10:09:59.072] call to Function() blocked by CSP # http://localhost:8080/:static/math/2.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML:29
However, I'm not getting a CSP report to the 'report-uri'. (As you see, I'm currently running the test through custom localhost port without SSL, in case that makes a difference. The colon before static is not a typo, I'm reserving all path parts starting with a colon for internal use of the application, all user content may freely define other URLs.)
Is my use of unsafe-eval attribute incorrect or is it impossible to allow unsafe-eval only for subset of 'self'? The intent is to allow unsafe-eval only for same origin path prefix /:static/math, strict CSP JS code execution for 'self' and no JS code for any other method.
There're multiple issues:
The Content-Security-Policy (CSP) header does not work this way. CSP only has granularity of a single host+port combination (origin). If you cannot allow all scripts to have unsafe-eval, no script can have it. The only possible workaround is to not use a script that requires unsafe-eval (fortunately, MathJax no longer requires unsafe-eval since MathJax bug 256 was fixed).
The allow syntax is an old Mozilla variant and should not be used. The current syntax is to say default-src followed by scheme or host names or origins that are allowed as source of everything and then override the default value for each sub type (e.g. script-src) as needed. Some sources may support additional source keywords in addition to self. For example, the script-src supports unsafe-eval which means that any script that is otherwise allowed to execute is allowed to run eval() or Function(), and unsafe-inline meaning that any piece of markup that can support some kind of inline script is allowed to execute. Allowing unsafe-eval may be acceptable but unsafe-inline is pretty much no-go with script-src (otherwise, you should not bother with the CSP at all).
The correct syntax for script-src as follows:
script-src 'self' cdnjs.cloudflare.com
combined with loading MathJax from https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js
MathJax also uses inline style attributes so following is needed (unless already allowed) or MathJax will raise Exception while trying to render the math:
style-src 'self' 'unsafe-inline'
It is not possible to use CSP to allow JS to insert style attributes and not have style attributes already inserted in the HTML source to have an effect.
It seems that Firefox 13.0 (at least) does not immediately "call home" in case of CSP violation. Most of the violation reports do get submitted some time after the event. Chrome seems to be much more aggressive with the report submission which will make it a bit easier to test. From my experience, Firefox does not always send CSP report at all - it may be using some kind of heuristic to not send repeated messages.
In the end, to make MathJax work with Content-Security-Protection, you need following headers (assuming you're using MathJax via CDNJS):
Content-Security-Policy: default-src 'self'; script-src 'self' cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline';
Older browsers (e.g. Firefox 13) used to require extra parameters such as options or required using non-standard headere name such as X-Content-Security-Policy or X-WebKit-CSP. These hacks are no longer required because user agents support standard header nowadays. (With the exception of MSIE in contrary to MS Edge.)
Year 2021 Update:
CSP version 2 allows specifying paths in origins, too. However, be warned that using paths is a breaking change where backwards compatibility is a bit unknown. The problematic part is that server needs to emit CSP header before it knows if user agent supports CSP1 or CSP2.

Categories