How to setup extra content-security-policy based on file type in koa? - node.js

The goal is to setup special rules for svg files,
server {
add_header Content-Security-Policy "default-src 'none'; child-src https://www.youtube.com; font-src 'self' https://fonts.gstatic.com; frame-ancestors 'none'; frame-src https://www.youtube.com; img-src 'self'; media-src 'self'; script-src 'self'; style-src 'self' https://fonts.googleapis.com";
location ~ \.svg$ {
add_header Content-Security-Policy "default-src 'none'; frame-ancestors 'none'; style-src 'self' 'unsafe-inline'";
}
}
for the 1st rule, we can do
ctx.response.set('Content-Security-Policy', 'default-src ...');
How about the 2nd line for the svg files.

Just use regular expression
const svgPattern = /.+\.svg$/;
if (filename.test(svgPattern)) {
// add required header
}

Related

CSP header read but apparently not understood

So, I am trying to obtain images from an API, doing like this:
fetch(callUrl, {method:'GET',
headers: {'Authorization': 'Basic ' + btoa('___')}})
.then(r => r.blob())
.then(bl => {
const imageObjectURL = URL.createObjectURL(bl);
$('<img/>',{src:imageObjectURL})
On IIS, I have :
<system.webServer>
<cors enabled="true">
<add origin="_mysite_"
allowCredentials="true"
maxAge="120">
<allowHeaders allowAllRequestedHeaders="true" />
</add>
</cors>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src 'self' http://mysite:* blob: data:; img-src 'self' http://mysite:* data: http: https: blob:;script-src 'self' 'unsafe-inline' 'unsafe-eval' http://mysite:*;style-src 'self' 'unsafe-inline';frame-src *" />
</customHeaders>
</httpProtocol>
</system.webServer>
Which results in a header being received:
Content-Security-Policy: default-src 'self' http://mysite:* blob: data:; img-src 'self' http://mysite:* data: http: https: blob:;script-src 'self' 'unsafe-inline' 'unsafe-eval' http://mysite:*;style-src 'self' 'unsafe-inline';frame-src *
Nevertheless, Chrome tells me:
Refused to load the image 'blob:http://gdcvmas163/bfece579-fe7c-49f7-99ef-9773b592acd3' because it violates the following Content Security Policy directive: "img-src 'self' data: https:".
Which to me seems like it doesnt read the header at all.
What is going on/ what am I missing?
Try to use below sample setting in your web.config. I know you want use http://mysite:*.
<add name="Content-Security-Policy" value="worker-src blob:; child-src blob: gap:; img-src 'self' blob: data:; default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap: content:" />
If it works, it means that the format or writing of our CSP value value is incorrect.
Please comment all the settings about CSP, and we can create a new html for test and add <meta> tag for test, until it works well.
<meta http-equiv="Content-Security-Policy"
content="
worker-src blob:;
child-src blob: gap:;
img-src 'self' blob: data:;
default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: gap: content:">

CSP 'self' is failing in various directives

I've recently added CSP to my website and started testing it (Report-Only): it looks OK except for some reports I cannot make sense of.
Specifically I am seeing violations for resources that should be allowed by a 'self' directive.
The server is running Express and CSP is served through helmet-csp. I've validated the CSP policy headers with multiple services (e.g. https://csp-evaluator.withgoogle.com/) and it comes out error-free.
I am using report-uri.com to collect and analyze CSP reports.
This is the helmet-csp setup:
app.use(csp({
directives: {
'default-src': ["'none'"],
'object-src': ["'none'"],
'script-src': ["'self'", (req, res) => `'nonce-${res.locals.nonce}'`],
'connect-src': ["'self'", (req, _res) => (req.protocol === 'http' ? 'ws://' : 'wss://') + req.get('host')],
'manifest-src': ["'self'"],
'worker-src': ["'self'"],
'style-src': ["'self'"],
'font-src': ["'self'"],
'img-src': ["'self'", 'data:'],
'base-uri': ["'self'"],
'form-action': ["'self'"],
'report-uri': '[REMOVED]'
},
reportOnly: true
}));
This is the resulting CSP header:
Content-Security-Policy-Report-Only: default-src 'none'; object-src 'none'; script-src 'self' 'nonce-[REMOVED]'; connect-src 'self' wss://MYSUBDOMAIN.MYDOMAIN.it; manifest-src 'self'; worker-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; base-uri 'self'; form-action 'self'; report-uri [REMOVED]
These are some example of the reports:
{
"csp-report": {
"document-uri": "https://MYSUBDOMAIN.MYDOMAIN.it/",
"effective-directive": "worker-src",
"original-policy": "default-src 'none'; object-src 'none'; script-src 'self' 'nonce-[removed]'; connect-src 'self' wss://MYSUBDOMAIN.MYDOMAIN.it; manifest-src 'self'; worker-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; base-uri 'self'; form-action 'self'; report-uri [REMOVED]",
"blocked-uri": "https://MYSUBDOMAIN.MYDOMAIN.it/notification-worker.js",
"line-number": 1,
"column-number": 1966,
"source-file": "https://MYSUBDOMAIN.MYDOMAIN.it/js/index.min.js"
}
}
{
"csp-report": {
"document-uri": "https://MYSUBDOMAIN.MYDOMAIN.it/results",
"effective-directive": "img-src",
"original-policy": "default-src 'none'; object-src 'none'; script-src 'self' 'nonce-[removed]'; connect-src 'self' wss://MYSUBDOMAIN.MYDOMAIN.it; manifest-src 'self'; worker-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; base-uri 'self'; form-action 'self'; report-uri [REMOVED]",
"blocked-uri": "https://MYSUBDOMAIN.MYDOMAIN.it/img/icon_twitter_black.png",
"line-number": 82
}
}
{
"csp-report": {
"document-uri": "https://MYSUBDOMAIN.MYDOMAIN.it/results",
"effective-directive": "style-src-elem",
"original-policy": "default-src 'none'; object-src 'none'; script-src 'self' 'nonce-[removed]'; connect-src 'self' wss://MYSUBDOMAIN.MYDOMAIN.it; manifest-src 'self'; worker-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; base-uri 'self'; form-action 'self'; report-uri [REMOVED]",
"blocked-uri": "https://MYSUBDOMAIN.MYDOMAIN.it/css/results.min.css",
"line-number": 8
}
}
There are ten or so similar reports (different images and css files, but identical report structure) and they all came from Chrome on Android.
I don't understand why all these reports were sent: in every case the relevant policy included the 'self' keyword.
Am I missing something obvious?

How to Allow Google fonts in IdentityServer4

To use Google fonts in IdentityServer3, the following Content-Security-Policy never worked:
<meta http-equiv="Content-Security-Policy"
content=" style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' 'unsafe-inline' https://fonts.gstatic.com data:">
Instead we configured the CspOptions in the idsrvApp.UseIdentityServer constructor which did work:
CspOptions = new CspOptions {
FontSrc = "https://fonts.gstatic.com",
StyleSrc = "https://fonts.googleapis.com",
Enabled = true
}
How can we configure CspOptions in IdentityServer4? I'm having trouble finding it.
For anyone else who gets stuck, the SecurityHeadersAttribute.cs file that comes with the IdentityServer4 quickstart files needs to be modified. Appending the following lines fixed it:
var csp = "default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self';";
// These two lines enable google fonts
csp += "font-src 'self' https://fonts.gstatic.com;";
csp += "style-src 'self' https://fonts.googleapis.com;";
The file is located in quickstart/SecurityHeadersAttribute.cs

CSP: multiple google uris and null?

we started to use Content Security Policy quite recently and still have a lot of problems with it.
1. blocked google URIs
A lot of google URIs get blocked for different directives. For example:
"csp-report": {
"blocked-uri": "https://www.google.co.za",
"document-uri": "https://de.our-project.com/",
"original-policy": "default-src https://de.our-project.com; script-src https://de.our-project.com data: https://*.our-project-test.com https://*.our-project.com https://*.our-project-stage.com https://s.yimg.jp https://www.google.co.jp https://p.dr.adingo.jp https://ajax.googleapis.com https://api.sovendus.com https://s.yjtag.jp https://data1.allo-pages.fr https://data1.mes-resultats.com https://*.yahoo.co.jp https://api.gutscheinconnection.de https://cdn.our-project-stage.com https://cdn.our-project.com http://www.googletagmanager.com https://www.googletagmanager.com https://www.google-analytics.com https://maps-api-ssl.google.com https://maps.googleapis.com https://www.googleadservices.com https://*.justuno.com http://connect.facebook.net https://connect.facebook.net https://pippio.com http://cdn.rawgit.com http://d.ratepay.com 'unsafe-inline' 'unsafe-eval'; style-src https://de.our-project.com https://*.our-project.com https://*.our-project-test.com https://www.sovendus.com https://cdn.our-project-stage.com https://cdn.our-project.com https://fast.fonts.net https://fonts.googleapis.com 'unsafe-inline'; img-src https://de.our-project.com data: https://*.our-project.com http://*.test.com https://*.test.com https://*.our-project-test.com https://www.google.com.co https://www.google.lt https://www.google.nl https://www.google.com.ua https://www.google.co.jp https://www.google.es https://www.google.co.uk https://www.google.dk https://www.google.co.il https://www.google.cz https://www.gstatic.com https://tap.rubiconproject.com https://sync.adap.tv https://d.agkn.com https://rudy.adsnative.com https://www.googletagmanager.com https://*.sovendus.com https://gum.criterio.com https://wam.solution.weborama.fr https://pippio.com https://load.s3.amazonaws.com http://test-admin.devnet.nil https://a248.e.akamai.net https://er.criteo.com https://ibeu2.mookie1.com https://tags.bluekai.com https://s.thebrighttag.com https://elr.sfr.fr https://traffic.outbrain.com https://ext.ligatus.com http://www.seur.com https://*.rlcdn.com https://www.google.ie https://www.google.fr https://cdn.our-project-stage.com https://cdn.our-project.com http://pim.test.com https://admin.our-project-stage.com https://admin.our-project.com https://pim-cdn.test.com http://pim-cdn.test.com https://cms-cdn.test.com http://test.preview.denkwerk.com https://www.facebook.com https://maps.googleapis.com https://maps-api-ssl.google.com https://googleads.g.doubleclick.net https://www.google-analytics.com https://www.google.de https://www.google.com https://stats.g.doubleclick.net https://csi.gstatic.com https://maps.gstatic.com http://aa.agkn.com https://aa.agkn.com http://login.dotomi.com https://login.dotomi.com http://emailretargeting.com https://emailretargeting.com https://p-eu.acxiom-online.com http://global.ib-ibi.com https://global.ib-ibi.com http://loadus.exelator.com https://loadus.exelator.com http://i.liadm.com https://i.liadm.com http://rc.rlcdn.com https://cm.g.doubleclick.net https://secure.insightexpressai.com https://e.nexac.com https://stags.bluekai.com https://pm.w55c.net https://um.simpli.fi https://dt-secure.videohub.tv https://c.bing.com https://b97.yahoo.co.jp; font-src https://de.our-project.com data: https://cdn.our-project-stage.com https://cdn.our-project.com https://fonts.gstatic.com 'unsafe-inline' 'unsafe-eval'; connect-src https://de.our-project.com https://profile.justuno.com https://www.justuno.com https://profilebak.justuno.com http://d.ratepay.com; media-src https://de.our-project.com; object-src https://de.our-project.com https://d.ratepay.com; child-src https://de.our-project.com https://bid.g.doubleclick.net https://www.youtube.com https://www.justuno.com; frame-src https://de.our-project.com https://bid.g.doubleclick.net https://www.youtube.com https://www.justuno.com; frame-ancestors https://de.our-project.com ; form-action https://de.our-project.com https://www.computop-paygate.com https://*.paypal.com https://www.sandbox.paypal.com; manifest-src https://de.our-project.com;",
"referrer": "https://de.our-project.com/",
"violated-directive": "img-src https://de.our-project.com data: https://*.our-project.com http://*.test.com https://*.test.com https://*.our-project-test.com https://www.google.com.co https://www.google.lt https://www.google.nl https://www.google.com.ua https://www.google.co.jp https://www.google.es https://www.google.co.uk https://www.google.dk https://www.google.co.il https://www.google.cz https://www.gstatic.com https://tap.rubiconproject.com https://sync.adap.tv https://d.agkn.com https://rudy.adsnative.com https://www.googletagmanager.com https://*.sovendus.com https://gum.criterio.com https://wam.solution.weborama.fr https://pippio.com https://load.s3.amazonaws.com http://test-admin.devnet.nil https://a248.e.akamai.net https://er.criteo.com https://ibeu2.mookie1.com https://tags.bluekai.com https://s.thebrighttag.com https://elr.sfr.fr https://traffic.outbrain.com https://ext.ligatus.com http://www.seur.com https://*.rlcdn.com https://www.google.ie https://www.google.fr https://cdn.our-project-stage.com https://cdn.our-project.com http://pim.test.com https://admin.our-project-stage.com https://admin.our-project.com https://pim-cdn.test.com http://pim-cdn.test.com https://cms-cdn.test.com http://test.preview.denkwerk.com https://www.facebook.com https://maps.googleapis.com https://maps-api-ssl.google.com https://googleads.g.doubleclick.net https://www.google-analytics.com https://www.google.de https://www.google.com https://stats.g.doubleclick.net https://csi.gstatic.com https://maps.gstatic.com http://aa.agkn.com https://aa.agkn.com http://login.dotomi.com https://login.dotomi.com http://emailretargeting.com https://emailretargeting.com https://p-eu.acxiom-online.com http://global.ib-ibi.com https://global.ib-ibi.com http://loadus.exelator.com https://loadus.exelator.com http://i.liadm.com https://i.liadm.com http://rc.rlcdn.com https://cm.g.doubleclick.net https://secure.insightexpressai.com https://e.nexac.com https://stags.bluekai.com https://pm.w55c.net https://um.simpli.fi https://dt-secure.videohub.tv https://c.bing.com https://b97.yahoo.co.jp"
}
But we don't even have this URI in our site. It's the same for a lot of other google URIs.
Does someone know why we get these violations and how to resolve them?
2. blocked-uri: null
There are a lot of
"blocked-uri": "null"
parts in our violation log. It's always the font-src directive, that takes action with this.
I've read about it being empty but couldn't find anything about "null".
Can anybody explain to me, how this happens?
EDIT
I've read some more into it now and it seems like google AdWords and analytics (?) are the reasons for my first problem.
Solution for this:
Either add ALL 200 or so google domains to your CSP or allow ALL image sources (or at least the specific protocol)
To my second problem:
It seems like "null" replaced the empty string. But all I found was about the script-src directive being violated, which either means the report is about inline javascript or an eval() function.
Both is not the case for me as the font-src directive is being violated.
If I find out something new, I'll edit the post again.
Found the solution myself:
1. blocked google URIs
Either add ALL 200 or so google domains to your CSP or allow ALL image sources (or at least the specific protocol)
2. blocked-uri: null, violated-directive: font-src
It seems like browser extensions cause this error. Namely lastpass. We tried it and on login the CSP threw the violation.
Hope this helps some people in the future.

Content Security Issues with IdentityServer 4 upgrade to version 1.5

I upgraded my Identityserver 4 to version 1.5.1 and now have content security policy errors.None of the solutions presribed so far has worked for me
I tried this
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline' https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js">
but nothing worthwhile is happening
In the IdentityServer4 Samples, the class SecurityHeadersAttribute.cs is responsible for sending the right CSP headers. You should only add the domain name:
var csp = "default-src 'self';" +
"img-src * 'self' data: https:;" +
"style-src 'self' ajax.aspnetcdn.com;" +
"font-src 'self' ajax.aspnetcdn.com;" +
"script-src 'self' ajax.aspnetcdn.com;"
// once for standards compliant browsers
if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy"))
{
context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp);
}
// and once again for IE
if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy"))
{
context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp);
}

Resources