I'm using NextJs#12 and I'm trying to set CSP for my application. I keep getting errors logged into my console and I have no idea what I'm doing wrongly. This is the policy I currently have in my netx.config file.
{
key: "Content-Security-Policy",
value: "default-src 'self' cdn.jsdelivr.net; script-src 'self' https://cdn.jsdelivr.net/npm/#shoelace-style/shoelace#2.0.0-beta.47/dist/chunks/chunk.HAL7R4WT.js https://embed.tawk.to/_s/v4/app/61adcafd0e1/js/twk-chunk-vendors.js https://js.paystack.co/v1/inline.js https://www.google-analytics.com/analytics.js https://www.googletagmanager.com/gtm.js 'unsafe-inline' 'unsafe-eval'; connect-src 'self' https://eljsuiwhwbb5lp5lmre5eifzuu.appsync-api.us-east-1.amazonaws.com https://embed.tawk.to https://va.tawk.to https://vitals.vercel-insights.com https://vsb75.tawk.to https://vsb89.tawk.to https://www.google-analytics.com wss://eljsuiwhwbb5lp5lmre5eifzuu.appsync-realtime-api.us-east-1.amazonaws.com wss://vsb75.tawk.to wss://vsb89.tawk.to; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://embed.tawk.to https://fonts.googleapis.com; img-src 'self' data: https://embed.tawk.to https://res.cloudinary.com https://tawk.link https://www.google-analytics.com;",
},
And this is the error so far:
I need help in solving this. I have been on it all day.
You would normally just have the hosts as sources in CSP, not the full url. I'm assuming your on https, so you don't need to specify that, but should keep wss in your policy. Try this instead:
default-src 'self' cdn.jsdelivr.net; script-src 'self' cdn.jsdelivr.net embed.tawk.to js.paystack.co www.google-analytics.com www.googletagmanager.com 'unsafe-inline' 'unsafe-eval'; connect-src 'self' eljsuiwhwbb5lp5lmre5eifzuu.appsync-api.us-east-1.amazonaws.com embed.tawk.to va.tawk.to vitals.vercel-insights.com vsb75.tawk.to vsb89.tawk.to www.google-analytics.com wss://eljsuiwhwbb5lp5lmre5eifzuu.appsync-realtime-api.us-east-1.amazonaws.com wss://vsb75.tawk.to wss://vsb89.tawk.to; style-src 'self' 'unsafe-inline' cdn.jsdelivr.net embed.tawk.to fonts.googleapis.com; img-src 'self' data: embed.tawk.to res.cloudinary.com tawk.link www.google-analytics.com;"
Related
I am working with the gatsby-plugin-csp and want to understand if it is possible to add two keywords both 'unsafe-inline' and 'unsafe-eval' in the same script-scr and make them work? Or do I need to create two different script-scr? There are a few sources that I must use and some them of need eval() and others inline scripts.
Can I do this?
// In your gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-plugin-csp`,
options: {
disableOnDev: true,
reportOnly: false, // Changes header to Content-Security-Policy-Report-Only for csp testing purposes
mergeScriptHashes: true, // you can disable scripts sha256 hashes
mergeStyleHashes: true, // you can disable styles sha256 hashes
mergeDefaultDirectives: true,
directives: {
"script-src": "'self' 'unsafe-inline' 'unsafe-eval' www.example.com",
"style-src": "'self' 'unsafe-inline'",
"img-src": "'self' data: www.google-analytics.com"
// you can add your directives or override defaults
}
}
}
]
};
Or should I do this?
// In your gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-plugin-csp`,
options: {
disableOnDev: true,
reportOnly: false, // Changes header to Content-Security-Policy-Report-Only for csp testing purposes
mergeScriptHashes: true, // you can disable scripts sha256 hashes
mergeStyleHashes: true, // you can disable styles sha256 hashes
mergeDefaultDirectives: true,
directives: {
"script-src": "'self' 'unsafe-inline' www.example.com",
"script-src": "'self' 'unsafe-eval' www.example.com",
"style-src": "'self' 'unsafe-inline'",
"img-src": "'self' data: www.google-analytics.com"
// you can add your directives or override defaults
}
}
}
]
};
I have tried using the first option with both 'unsafe-inline' and 'unsafe-eval' in this case half of them give errors like Refused to load the script 'http://embed.example.com/next/embed.js' because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' 'unsafe-eval'
I also get this error Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google-analytics.com https://www.googletagmanager.com
When I change the order of the keywords putting 'unsafe-eval' then 'unsafe-inline' I still get errors refusing to run other scripts.
You could have two CSPs defined, but not the same directive twice in one policy. If you define multiple policies, your content still needs to pass all policies, adding another one can only make it stricter.
Your first script-src is "'self' 'unsafe-inline' 'unsafe-eval' www.example.com", which allows anything from the same server (same host, same port and same or safer scheme), inline scripts, eval (new Function(), setInterval(), setTimeout() and eval()) and scripts from www.example.com.
Your first error is caused by script from embed.example.com, which is blocked by your policy which only allows 'self' and www.example.com. You can add embed.example.com or replace www.example.com with *.example.com.
The second error is likely related to inline event attributes (like onclick, onload etc), click on the link in the error message to see the violating code. You generally need to rewrite them using event handlers. You might be able to allow them with additional efforts in CSP level 3, but I don't think there is full browser compatibility yet.
I've been struggling with this issue for few weeks now. No matter what changes I make to my CSP - I still get the same error. I'm not sure if it has anything to do with my CSP headers or not.
Set up:
I have an angular 13 SPA with a NodeJS back end.
I used NPM to install
"#angular/google-maps": "^13.3.2",
"#googlemaps/js-api-loader": "^1.14.3",
I import the methods in my dashboard.ts file:
import { Loader } from "#googlemaps/js-api-loader";
I used to following code snip it in my ngOnInit():
let loader = new Loader({
apiKey: '--------------------------',
});
loader.load().then(() => {
console.log('loaded gmaps')
const location = { lat: 51.233334, lng: 6.783333 }
this.map = new google.maps.Map(document.getElementById("map"), {
center: location,
zoom: 6
})
const marker = new google.maps.Marker({
position: location,
map: this.map,
});
})
I modified my Content Security Header to be:
<meta http-equiv="Content-Security-Policy"
content="script-src 'self' maps.googleapis.com;
img-src 'self' data: maps.gstatic.com *.googleapis.com *.ggpht.com;
font-src https://fonts.gstatic.com/ 'unsafe-inline';
style-src 'self' https://fonts.googleapis.com 'unsafe-inline';
style-src-elem 'self' https://fonts.googleapis.com 'unsafe-inline';
/>
No matter what I do - I always get the same error:
74.6f64f0c92cc7c0a0.js:346 Refused to load the script 'https://maps.googleapis.com/maps/api/js?callback=__googleMapsCallback&key=---------------'
because it violates the following Content Security Policy directive:
"script-src 'self'". Note that 'script-src-elem' was not explicitly
set, so 'script-src' is used as a fallback.
Any insight would be greatly appreciated!
The CSP in the error message has script-src "script-src 'self'" while the one you have defined has "'self' maps.googleapis.com". Most likely there are two CSPs defined, and all content has to pass all policies. Your policy is defined as a meta tag. Look for CSP defined in a response header as well. You will need to determine why and where the other CSP is set and then change or remove it.
Figured it out. Basically, my Angular APP was being served by my NodeJS application. My NodeJS application is using Helmet and it seems that the default CSP from Helmet was over riding the Angular CSP set up in the index.html.
I am currently making a small application that is trying to fetch data from an API. To begin, I used electron-forge's webpack and react template to get started.
Without any CSP configuration in the meta tag of the HTML file, I get this error:
Added the following CSP to my main HTML file:
<meta
charset="UTF-8"
http-equiv="Content-Security-Policy"
content="default-src 'self' 'unsafe-inline' data: https://api.flybywire.com/;"
/>
This results in this error with a blank page in the renderer (before, it displayed the rest of the page correctly).
If I add 'unsafe-eval' to the CSP, I get this.
The strange thing is it appears that there are two CSP policies going on here. I have made an electron app without WebPack before that fetched data online with no issue, and I am unfamiliar with it. I have a feeling the issue lies in there.
I've tried editing my webpack.renderer.config.js by adding devtool: "eval-source-map" under module.exports to no avail.
The source code is available under this github repository , however I haven't pushed the version that calls the data fetching function which is located in metar.jsx.
Any help would be greatly appreciated as I have been scouring around for a fix for days now.
Found the solution.
As I suspected, there was indeed a separate security policy. However, if using electron-forge, there is a way to specify this in your package.json by adding
"devContentSecurityPolicy":"default-src * self blob: data: gap:; style-src * self 'unsafe-inline' blob: data: gap:; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: data: gap:; object-src * 'self' blob: data: gap:; img-src * self 'unsafe-inline' blob: data: gap:; connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;"
Just like this
[
"#electron-forge/plugin-webpack",
{
"devContentSecurityPolicy":"default-src * self blob: data: gap:; style-src * self 'unsafe-inline' blob: data: gap:; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: data: gap:; object-src * 'self' blob: data: gap:; img-src * self 'unsafe-inline' blob: data: gap:; connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;",
"mainConfig": "./webpack.main.config.js",
"renderer": {
"config": "./webpack.renderer.config.js",
"entryPoints": [
{
"html": "./src/index.html",
"js": "./src/renderer.js",
"name": "main_window"
}
]
Just a caveat, that CSP is highly insecure because it allows everything in the document. It should be modified to include only what is needed later. However, I'm glad to have found where this hidden setting was.
i am trying to render a chart in my app using Pug as seen below:
block content
h2 Question statistics
.col-lg-12
script(src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js")
.chart-container
canvas#myChart2
script.
var ctx = document.getElementById("myChart2").getContext('2d');
ctx.canvas.parentNode.style.width = '50%'
var idata = [1]
var ilabel = [2]
var myChart = new Chart(ctx, { /* ... etc */
This was loaded just fine before a week or so but today when i tried to access this feature the chart would not render.
The error in my console is this:
Refused to load the script
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js'
because it violates the following Content Security Policy directive:
"script-src 'self'". Note that 'script-src-elem' was not explicitly
set, so 'script-src' is used as a fallback.
and
Refused to execute inline script because it violates the following
Content Security Policy directive: "script-src 'self'". Either the
'unsafe-inline' keyword, a hash
('sha256-AklvVxShqs4WBi3vUz7qSiPkes2rSVGoNyoZXYVnSA8='), or a nonce
('nonce-...') is required to enable inline execution.
This is the first time i am seeing this error and i don't know how to solve it. Any ideas?
As turned out in comments, here's the line of code that broke it all:
app.use(helmet());
Helmet is a really neat module designed to let you protect your server from the most common attack vectors without worrying much about details. Alas, as any good security tool, it operates in 'paranoid mode' by default. Here's what this small line is actually equivalent to:
app.use(helmet.contentSecurityPolicy());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.expectCt());
app.use(helmet.frameguard());
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts());
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy());
app.use(helmet.xssFilter());
Yep, a lot of stuff. The one that messed up your setup is the first item of this list. Here's the default values sent as Content-Security-Policy header values by that line:
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
Once again, that makes sense, as Helmet doesn't know anything about external entities you're using - and your level of trust to those. It's you who are responsible for providing this data, either by adding hash info or by listing the trusted sources in the configuration. For example:
helmet.contentSecurityPolicy({
useDefaults: false,
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "example.com"], // scripts from example.com are now trusted
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
},
})
You can configure each module individually, or add this configuration into helmet directly:
app.use(
helmet({
contentSecurityPolicy: {
useDefaults: false,
directives: { ... }
},
})
);
So I'm setting up a helmet-csp(https://www.npmjs.com/package/helmet-csp), and are running ace. Here's my helmet-setup:
var csp = require("helmet-csp");
app.use(csp({
directives: {
defaultSrc: ["'self'", "https://localhost:8000"],
styleSrc: ["'self'", "'unsafe-inline'"],
sandbox: ["allow-forms", "allow-scripts", "allow-same-origin"],
reportUri: "/report-violation",
scriptSrc: ["'self'", "'unsafe-inline'",
"https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js",
"https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-monokai.js",
"https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-javascript.js"]
}
}));
and the script is implemented like this(the src is linked to a local embedment of ace):
<script src="../../src-min-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
var editor = ace.edit("editor");
editor.getSession().setUseWorker(false);
editor.setTheme("ace/theme/monokai");
editor.getSession().setMode("ace/mode/javascript");
</script>
Which works with no devastating errors, but I keep getting this in browser-console:
Refused to create a worker from 'blob:https://localhost:8000/34145ece-2c95-403b-92b0-79d02a5b4edd' because it violates the following Content Security Policy directive: "default-src 'self' https://localhost:8000". Note that 'worker-src' was not explicitly set, so 'default-src' is used as a fallback.
and
Could not load worker DOMException: Failed to construct 'Worker': Access to the script at 'blob:https://localhost:8000/701e5193-c7f3-47b4-94da-c2086bfc2dd4' is denied by the document's Content Security Policy.
at new u (https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js:1:305119)
at createWorker (https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-javascript.js:1:22584)
at p.$startWorker (https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js:1:159829)
at p.$onChangeMode (https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js:1:159064)
at p.<anonymous> (https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js:1:158825)
at https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js:1:55143
at Array.forEach (native)
at https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js:1:55120
at n (https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js:1:936)
at a (https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js:1:1487)
Feels like I've tried everything google has to offer, but no result. Can anybody help me?
I had to add child-srcpolicies for the worker to work. Since the worker sent some kind of blob, i allowed blobs from that origin.
app.use(csp({
directives: {
defaultSrc: ["'self'"],
imgSrc: ["data: *"],
childSrc: ["blob: *"],
styleSrc: ["'self'", "'unsafe-inline'",
"https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"],
sandbox: ["allow-forms", "allow-scripts", "allow-same-origin"],
scriptSrc: ["'self'", "'unsafe-inline'", "https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js",
"https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-monokai.js",
"https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-javascript.js",
"https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/worker-javascript.js"],
fontSrc: ["'self'", "https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/fonts/fontawesome-webfont.woff2?v=4.7.0",
"https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/fonts/fontawesome-webfont.woff?v=4.7.0]",
"https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/fonts/fontawesome-webfont.ttf?v=4.7.0",
"https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/worker-javascript.js"]
}
}));
Also I made some changes to the script for it to work. Why it worked after that, I don't know:
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js"></script>
<script>
var textarea = document.querySelector("#content");
var editor = ace.edit("editor");
editor.setTheme("ace/theme/monokai");
editor.getSession().setMode("ace/mode/javascript");
editor.getSession().on("change", function () {
textarea.innerHTML = editor.getSession().getValue();
});
textarea.innerHTML = editor.getSession().getValue();
</script>
There is no need to include ace URLs in "script-src" ,you can use like this
scriptSrc: ["'self'", "'unsafe-eval'", 'blob:', 'data:'],
It will work
I am using apache web server headers to set the content security policy.
I added blob: to the script-src directive and it worked ok.
Header set Content-Security-Policy "default-src 'self'; media-src *; img-src ; font-src 'self' data:; script-src 'self' 'unsafe-eval' 'unsafe-inline' blob: https://.googleapis.com https://.google.com https://.google-analytics.com https://*.gstatic.com; style-src 'self' 'unsafe-inline'; object-src 'self';"