How to set headers for content security policy...
I tried it in Angular and set the headers
Set header in app.js:
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"frame-ancestors 'self'; default-src 'unsafe-inline' 'self'; font-src 'unsafe-inline' 'self'; img-src 'self' 'unsafe-inline' blob: data: 'unsafe-eval'; script-src 'unsafe-inline' 'self'; style-src 'self' 'unsafe-inline'; frame-src 'unsafe-inline' 'self'"
);
next();
});
Related
I'm starting to learn node to build an web api using express with Typescript.
My goal is to build an api that consume a module called "psn-api" that give information from Psn(Playstation Network) logged user.
But when I try to call the module function that call an external API I get an error saying 'Content Security Policy: The page’s settings blocked the loading of a resource at http://localhost:3000/favicon.ico (“default-src”).'
Is there a configuration on node that I need to make to disable this Security Policy?
import express from 'express';
import { exchangeCodeForAccessToken, exchangeNpssoForCode,getUserTrophyProfileSummary } from "psn-api";
const app = express()
const port = 3000
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
const myNpsso = "userToken";
app.get('/trophySummary', (req, res) => {
var result = getUserTrophySummary();
res.send(result)
})
async function getUserTrophySummary(){
// We'll exchange your NPSSO for a special access code.
const accessCode = await exchangeNpssoForCode(myNpsso);
// We can use the access code to get your access token and refresh token.
const authorization = await exchangeCodeForAccessToken(accessCode);
return getUserTrophyProfileSummary(authorization,"me");
}
I already try setting the res.header to many different configurations but no result
res.setHeader(
'Content-Security-Policy', "default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'"
);
I've search in some security websites how to configure correctly Nginx server and node.js using helmet. But even adding all add_header rules, OWASP ZAP software is getting two medium vulnerabilities, I would like to know how can I fix it.
The first one is related to robots.txt CSP
I don't know why this is happening I'm not even giving disallow url information in robots.txt, why this is actually a vulnerability?
Sitemap: https://example.com/sitemap.xml
User-agent: *
Allow: /
The second medium vulnerability is CSP Wildcard Directive
Now I'll share my nginx full configuration and node.js helmet middlewares, maybe I'm forgetting something.
Nginx server configuration:
server {
listen 80 default_server;
listen [::]:80;
server_name _;
add_header Content-Security-Policy "default-src 'self'; script-src 'report-sample' 'self'; style-src 'report-sample' 'self' https://cdn.jsdelivr.net https>
add_header 'Access-Control-Allow-Origin' 'https://gorilafreela.com.br' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection 1;
add_header Strict-Transport-Security: max-age=31536000;
add_header X-Content-Type-Options "nosniff";
add_header Expect-CT 'enforce; max-age=7776000';
# gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
# robots.txt
location = /robots.txt {
root /var/www/html;
log_not_found off;
access_log off;
}
# front-end
location / {
root /var/www/html;
try_files $uri /index.html;
}
# node api
location /api/ {
proxy_pass http://localhost:3000/;
proxy_redirect off;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
}
}
Node.js and helmet app.js
/**
* Requiring dependencies
*/
const express = require('express');
const cors = require('cors');
const helmet = require("helmet");
/**
* Express app
*/
const app = express();
if (process.env['NODE_ENV'] == 'prod') {
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') !== 'https') {
res.redirect(`https://${req.header('host')}${req.url}`);
} else {
next();
}
});
}
app.use(helmet());
app.disable('x-powered-by');
app.use(
helmet.contentSecurityPolicy({
directives: {
"default-src": ["'self'"],
"script-src": ["'self'"],
"style-src": ["'self'", 'https://cdn.jsdelivr.net', 'https://fonts.googleapis.com'],
"object-src": ['none'],
"base-uri": ["'self'"],
"connect-src": ["'self'"],
"font-src": ["'self'", 'https://cdn.jsdelivr.net', 'https://fonts.gstatic.com'],
"frame-src": ["'self'"],
"img-src": ["'self'", 'https://res.cloudinary.com'],
"manifest-src": ["'self'"],
"media-src": ["'self'"],
"worker-src": ['none'],
},
})
);
app.use(
helmet.referrerPolicy({
policy: ["origin", "unsafe-url"],
})
);
app.use(
helmet.frameguard({
action: "deny",
})
);
app.use(
helmet.dnsPrefetchControl({
allow: true,
})
);
// Sets "Strict-Transport-Security: max-age=123456; includeSubDomains; preload"
app.use(
helmet.hsts({
maxAge: 31536000,
preload: true,
})
);
app.use(
helmet.expectCt({
maxAge: 7776000,
enforce: true
})
);
app.use(helmet.ieNoOpen());
app.use(helmet.xssFilter());
app.use(helmet.originAgentCluster());
app.use(helmet.noSniff());
app.use(cors());
app.use(express.json());
app.use(loginMiddleware.action);
app.use(roleValidationMiddleware.action);
/**
* Server port
*/
const port = 3000;
I am not able to attach the google form to my website while using helmet js. What could be the code to allow it?
iframe
<iframe src="https://docs.google.com/forms/d/e/..." width="600" height="850px" class="col-12" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
Helmet Middleware
app.use(helmet({
contentSecurityPolicy: {
directives: {
frameSrc: ["'self'", "https://docs.google.com/forms"],
}
},
}));
Error on Client-Side
Refused to frame 'https://docs.google.com/forms' because it violates
the following Content Security Policy directive: "default-src 'self'".
Note that 'frame-src' was not explicitly set, so 'default-src' is used
as a fallback.
Finally, I got the solution.
We need to set COEP (Cross-Origin-Embedder-Policy) response header if we want to embed any link with the website.
app.use(helmet({
contentSecurityPolicy: {
directives: {
"frame-ancestors": ["'self'", "*.google.com/"],
frameSrc: ["'self'", "*.google.com/"],
childSrc: ["'self'", "*.google.com/"]
}
},
// crossOriginEmbedderPolicy: false
}));
app.use((req, res, next) => {
res.header("Cross-Origin-Embedder-Policy", "cross-origin")
next()
})
after i uploaded my website on herokuy the images do not working and it gave me that error
Refused to load the image '' because it violates the following Content Security Policy directive: "img-src 'self' data:".
i have tried somethings like
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; font-src data:" />
that but it does not work also
This disables the contentSecurityPolicy middleware but keeps the rest:
app.use(
helmet({
contentSecurityPolicy: false,
})
);
Better practice instead of setting contentSecurityPolicy to false which should be the most last option. Using the Helmet documentation helps alot. I used this in my app and it solves the issue very well. My app is hosted here. Checkout my source code here.
app.use(
helmet.contentSecurityPolicy({
useDefaults: true,
directives: {
"img-src": ["'self'", "https: data:"]
}
})
)
app.use(helmet({ crossOriginEmbedderPolicy: false, originAgentCluster: true }));
app.use(
helmet.contentSecurityPolicy({
useDefaults: true,
directives: {
"img-src": ["'self'", "https: data: blob:"],
},
})
);
I am working with Visual Studio's Tools for Apache Cordova.
When I build the app with Ripple, all is well. But when I build it to my android device, the app refuses to connect to my external API.
This is the error in the JavaScript Console log:
Refused to connect to 'http://XXX.herokuapp.com/api/posts/0/5' because it violates the following Content Security Policy directive: "default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'".
Note that 'connect-src' was not explicitly set, so 'default-src' is
used as a fallback.
And:
Error: Failed to execute 'open' on 'XMLHttpRequest': Refused to
connect to 'http:// XXX. herokuapp. com/api/posts/0/5'
My API is built with Node.js and express. There is Access-Control-Allow-Headers in my server.js, but it still doesn't work on my device.
Server.js:
//'use strict';
var express = require('express'); // call express
var app = express(); // define our app using express
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var router = express.Router();
var fs = require('fs');
var path = require('path');
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use(bodyParser.urlencoded({ extended: true })); // parse application/x-www-form-urlencoded
app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT
app.use(express.static(__dirname + '/www'));
// middleware to use for all requests
app.use(function (req, res, next) {
console.log('in middleware');
res.setHeader('Access-Control-Allow-Origin', '*');//allowing ripple's localhost get access to node's localhost(5432).
console.log(req.header);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers',"X-Requested-With,Content-Type");
//res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
require('./app/routes')(app); // pass our application into our routes -- must
app.use('/api', router);//put this line beofre passing app to routes.js for it to take effect.
var port = process.env.PORT || 8080;
app.listen(port, function() {
console.log("Listening on " + port);
});
exports = module.exports = app; // expose app
I have also tried adding a meta tag to my index.html file, but with no success.
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval' http://localhost:8080 http://XXX.herokuapp.com">
Any ideas what might be the problem?
From the Error Message. You are calling Ajax Request in your JS. But you only added http://XXX.herokuapp.com after script-src, which only allows loading the script content. To allow the Ajax request, http://XXX.herokuapp.com needs to be added after connect-srclike this:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; connect-src 'self' http://XXX.herokuapp.com; style-src 'self' 'unsafe-inline'; media-src *">
Alternatively, you can add the URL after default-src, which sets a default policy for allowing everything(loading script/CSS contents,Ajax Request and so on). So the meta Tag should be like this:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' http://XXX.herokuapp.com data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
For detailed information about Content Security Policy you can refer to Content Security Policy Reference.