I have a react (create-react-app, not ejected) front end, node/express back end with the following csp config:
app.use(
helmet.contentSecurityPolicy({
directives: {
'script-src': [
"'self'",
"'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='",
"'sha256-10e801rrdN2Gq8YctvySwnSlugHJX+Xjgx1mhmij72w='",
"'sha256-e89fobGAetuB/6VgXYgfYEJo7toSqmridYOdrJoE6LU='",
"'strict-dynamic'",
'http:',
'https:',
"'unsafe-inline'",
],
'object-src': ["'none'"],
'base-uri': ["'none'"],
},
})
)
The hashes you see there were provided in previous csp errors. I located the three scripts, and used a hash tool and verified that the hashes in the above directives belong to those three scripts.
When I publish to heroku with this configuration, I test the url with https://csp-evaluator.withgoogle.com/ and it says everything is A-ok.
But my site will not render, and in chrome devtools I get the following CSP error, "Content Security Policy of your site blocks some resources":
As you can see, it's blocking resources from the host url, not 3rd party.
The scripts from the errors look like this, in index.html:
<script src="/static/js/runtime-main.11477cd6.js"></script>
<script src="/static/js/7.e1d80075.chunk.js"></script>
<script src="/static/js/main.c7392c1f.chunk.js"></script>
I visited the link provided with the error, "See how to set a strict CSP" and followed their instructions (to the letter) for hash based CSP, and only when that did not work, I added 'self', 'http:', 'https:', and 'unsafe-inline'. I think those are ok to leave there, they don't seem to be causing any problem. I even tried adding the actual domain, but nothing changed.
I have set the INLINE_RUNTIME_CHUNK=false environment variable, needed for CRA apps (in heroku config as well) which fixed some previous (different) problems, but now this is happening.
I thought maybe the problem was that the hash was made from the path to the script, literally src="/path/file.js" and not the actual script in that file, so I hashed those three scripts and added those hashes to the directives. Still not working.
Additionally, I noticed that with nonces, the examples show the script tag with an added nonce property, like <script src="something.js" nonce="noncerandom"></script> so, I tried to use 'integrity' with the hashes of the scripts, (not the file paths.) Now, there are no errors whatsoever, but also, nothing is rendering. There is nothing inside the root <div>s.
I give up! Please help. I have read at least 50 related questions on stackoverflow, followed every link recommended in the comments & answers, re-written and re-deployed 106 times according to heroku. (None of the problems happen on localhost, so I have to republish every time.)
Turns out, the script-src hashes AND the <script> tag integrity values must both be added, even when using middleware like helmet. I got the wrong impression that you didn't need to bother updating <script> tags unless you were setting your headers in a <meta> tag, but in fact, they are required in any case.
That means you have to manually replace all those hashes after every front end build, as those scripts will change. Not a big deal imo, just an extra manual chore during development. There's probably a package for that somewhere.
Here's what my helmet config ended up looking like:
app.use(
helmet.contentSecurityPolicy({
directives: {
'img-src': [
"'self'",
'data:',
'flagcdn.com',
'upload.wikimedia.org',
'openweathermap.org',
'hereapi.com',
'js.api.here.com',
],
'default-src': ["'none'"],
'script-src': [
"'sha256-gpDxdDuBGxxl88r6aymWROliaETfsyODwU6dpFZyIUU='",
"'sha256-33dcmxHc726AphEOtauUa39NPzHtsEPzEAX8PKd8NU0='",
"'sha256-vqol01UCQbQtIbFsadt22MWtP/EzXBhlXJVTdE3Z0Nk='",
"'sha256-vnJfeIr7hNIEwFqAV/GfKdJDn1SeGTUHl87WXU7cOxA='",
"'strict-dynamic'",
],
'object-src': ["'none'"],
'base-uri': ["'none'"],
'connect-src': [
'sheltered-scrubland-08732.herokuapp.com',
'https://*.here.com:*',
'https://*.hereapi.com:*',
'blob:',
],
'worker-src': ["'self'", 'blob:'],
'manifest-src': ['https://sheltered-scrubland-08732.herokuapp.com'],
// 'require-trusted-types-for': [`'script'`], // cannot use. 'script' value requires further specifications which are a mystery to solve some other time.
},
})
)
And here's the <script> tags in index.html:
<script
src="/static/js/runtime-main.11477cd6.js"
integrity="sha256-gpDxdDuBGxxl88r6aymWROliaETfsyODwU6dpFZyIUU="
></script>
<script
src="/static/js/7.e1d80075.chunk.js"
integrity="sha256-33dcmxHc726AphEOtauUa39NPzHtsEPzEAX8PKd8NU0="
></script>
<script
src="/static/js/main.c7392c1f.chunk.js"
integrity="sha256-vqol01UCQbQtIbFsadt22MWtP/EzXBhlXJVTdE3Z0Nk="
></script>
To get those hashes, I copied and pasted the actual source code from runtime-main.11477cd6.js etc., into https://report-uri.com/home/hash. This is something I never read about ANYwhere, but it did not make sense to me to make a hash out of <script> tags with file paths. What would be the point of hashing a file path??? And in more than one article, they actually suggested using the hashes provided in the devtools csp error messages, which I discovered were made from the file path script tags, which is probably why nothing was working at first. smh.
I have the following csp embedded in my aws instance, however it doesn't seem to be properly configured, when I scan via Mozilla Observatory, I get the following message: Content Security Policy (CSP) implemented unsafely.
Header set Content-Security-Policy "default-src 'unsafe-inline' https://vlibras.gov.br https://*.chargebee.com https://*.chargebeeportal.com https://*.cloudfront.net https://*.jobconvo.com https://*.amazonaws.com https://www.google-analytics.com https://jobconvo.freshdesk.com https://assets.freshdesk.com https://*.googleapis.com https://gitcdn.github.io https://*.youtube.com https://*.gstatic.com https://*.doubleclick.net https://www.google.com/recaptcha/ https://www.google.com object-src data: 'unsafe-eval' blob: 'unsafe-eval' font-src: 'self' data;"
After studying a little, am I right to think that the problem is in the unsafe-inline parameter? If so how can I get around this since I already have embedded HTML in onClick ()
Firstly, your CPS has a fatal errors - you missed ; between directives and used a wrong directives name like 'font-src:'.
Mozilla Observatory assumes CSP unsafe, because of use unsafe tokens 'unsafe-eval' and 'unsafe-inline' in in script-src/default-src.
I already have embedded HTML in onClick ()
To avoid 'unsafe-inline' you can use addEventListener("click", ) instead of <tag onClick='...'>.
To avoid 'unsafe-eval' it need to know which unsafe constructs do you use - eval() Function(), setInterval() or setTimeout(). The last two can be fixed easily (pls see in comments).
Browser - Chrome Version 85.0.4183.102
There are lot of threads around this topic but I could not find what is the safest and correct way to deal with 3rd party libraries.
I am using kendo grid (jQuery) in my chrome extension.. it has "unsafe-eval" and "unsafe-inline"... unless I set the below entry in manifest.json its not working.
"content_security_policy": "font-src data:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval'; object-src 'self';"
Since its not safest practice.. how can I bypass this with hash or nonce.
Note: The Kendo library is downloaded and referred from local machine. (No CDN references)
'unsafe-line'
When I remove 'unsafe-inline' as expected its giving out 5 errors in my case and providing 5 different sha-256 hashes. I replaced 'unsafe-inline' with 5 hashes but still getting the same error.
Below is the error when I tried only with 1 hash.
Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' 'sha256-lzhPGNqxpwmBda/ftMrdga7dSTDWPq2rpjz66R6TVFw='". Either the 'unsafe-inline' keyword, a hash ('sha256-lzhPGNqxpwmBda/ftMrdga7dSTDWPq2rpjz66R6TVFw='), or a nonce ('nonce-...') is required to enable inline execution.
'unsafe-eval'
When I remove 'unsafe-eval' as expected giving out errors with no generated hash to replace.
'font-src data:'
yet to attempt to bypass.
I even tried nonce but did not work.
am I missing something? or do I need to live with 'unsafe-inline' and 'unsafe-eval'. If yes, what is the potential risk? I am planning to release this extension to public.
EDIT: I tried sandbox as suggested below.
Here is what I did.
index.html
<html>
<head>
<link href="css/iframe.css" rel="stylesheet">
</head>
<body>
<iframe id="iframe" src="sandbox.html"></iframe>
</body>
</html>
sandbox.html has kendo reference <script src="js/kendo.all.min.js"></script>
Here is the manifest.json change
"sandbox": {
"pages:": [
"sandbox.html"
]},"content_security_policy": "sandbox allow-scripts allow-same-origin allow-popups;"
I am still getting errors with kendo. Any suggestions?
'unsafe-inline' in scripts and styles
Chrome unintentionally misleads you with hashes for inline styles. The same is with hashes for inline scripts:
<script>...</script> consiedres as inline and can be allowed with 'nonce-value' or/and 'hash-value' tokens.
<tag onEvent='event_handler_script'> and <a href='javascript:click_handler_script'> both considers as inlnie script but cannot be allowed by 'nonce-value' or/and 'hash-value' tokens. But Chrome calculates sha256 for them, because it prepares to implement 'unsafe-hashes' token (spec section is not normative so implementation is delayed support is implemented already).
Therefore is case (1) you could easily ged rid of 'unsafe-inline', in case (2) - you need to modify code first.
'unsafe-eval' in scripts
Content Security Policy spec does not provide way to allow unsafe scripts constructions via 'nonce/hash' tokens. Changes of the script code will be required, in some cases - purely "cosmetic".
CSP considers as eval-constructs:
eval()
setTimeout('string')
setInterval('string')
Function()
setImmediate()
execScript()
Note that setTimeout()/setInterval() are "eval" only when callback function passed as a string. If callback is an anonymous funct or "function by name" - those not fall under eval.
In this case, you can easily get rid of eval without changing the logic of the script.
For Chrome Manifest 3 you can add
{
"content_security_policy":{
"extension_page": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'" ,
"sandbox": "extension_page": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'" ,
}
}
I have a Chrome extension that makes a POST request to my website from the extension's background script. I get the following error (shown in Chrome's extension manager):
Refused to connect to 'https://my.website.com/path/' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
It's honestly not even clear to me if I need to change something in the js code or server-side.
background.js:
var xmlHttp;
function makerequest(){
xmlHttp=new XMLHttpRequest();
xmlHttp.open("POST", "https://my.website.com/path/",true);
xmlHttp.onreadystatechange = got_response;
var formData = new FormData();
xmlHttp.send(formData);
}
function got_response(){
if (xmlHttp.readyState == 4){
alert(xmlHttp.responseText);
}
}
The manifest includes:
"permissions": ["activeTab", "*://my.website.com/*","contextMenus"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_security_policy":"connect-src 'self' https://my.website.com/*",
I have seen that there are other related question/answers. However, they are either trying to access someone else's website (not one I control) or there is an issue with using inline code, which doesn't seem to be the issue here since the code is in background.js (or if it is, please explain!). If you suggest another answer, or vote to close, please please actually checks that the other answer answers THIS question.
You need to remove the trailing asterisk from your CSP string. Asterisks are not interpreted as wildcard characters in the path part of a source identifier in CSP strings. Your current CSP string only allows connections to the literal URL https://my.website.com/*.
Content Security Policy Level 2 specification explicitly says:
The rules for matching source expressions that contain paths are
simpler than they look: paths that end with the '/' character match
all files in a directory and its subdirectories. Paths that do not end
with the '/' character match only one specific file.
Apart from that, the CSP string in the manifest should limit script-src and object-src (either explicitly or using default-src). If it doesn't do that, Chrome displays warnings on the extension details page.
The CSP line in your manifest should therefore look like this:
"content_security_policy":"default-src 'self'; connect-src 'self' https://my.website.com/",
I've been using CSP on my localhost server, and as well as normal CSP messages, have seen this:
{
"csp-report": {
"document-uri": "https://localhost:3000/",
"referrer": "",
"violated-directive": "script-src 'self' 'unsafe-eval' cdn.mxpnl.com js.stripe.com platform.twitter.com syndication.twitter.com use.typekit.net",
"effective-directive": "script-src",
"original-policy": veryLongPOlicyGoesHere,
"blocked-uri": "",
"source-file": "https://platform.twitter.com",
"line-number": 2,
"column-number": 28911,
"status-code": 0
}
}
Why is blocked-uri" ""? What's causing this CSP warning?
While it may not be easy to parse, you can find information about that type of report in a CSP "fingerprint" project I ran for a while: https://gist.github.com/oreoshake/29edbf9aae8125f05b66
Empty blocked-uris indicate an inline script/style violation, an eval call, or an inline event handler/javascript: href. Your violated-directive allows eval however.
If you can trigger the same error in a Firefox browser, you can inspect the script-sample field. It may contain the content of the inline script or it may mention the event handler triggered or it will include "eval" in the message.
A very large number of unexpected reports in this format come from browser extensions, namely lastpass.