I am using Helmet to set up the content security policies of my web app in the backend using Express. The policies look like the following:
const express = require("express");
const app = express();
const helmet = require('helmet');
app.use(helmet());
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://ajax.googleapis.com"],
imgSrc: ["https://firebasestorage.googleapis.com"],
objectSrc: ["'none'"],
styleSrc: ["'self'", "https://maxcdn.bootstrapcdn.com/bootstrap", "https://www.w3schools.com"],
upgradeInsecureRequests: [],
},
})
);
When my app tries to access a link such as https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css
. It says that it violates the styleSrc policy. But I have specified as one of the policies that https://maxcdn.bootstrapcdn.com/bootstrap
is allowed, I thought with that https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css
would be accepted as well, since it is a child src. But apparently it gets blocked. How do I allow the child src to pass then? I have tried https://maxcdn.bootstrapcdn.com/bootstrap*
but it is invalid.
Author of Helmet here.
Try adding a trailing slash, like this:
This is because
/bootstrap
doesn't let you do things like/bootstrap/3.4.0/css/bootstrap.min.css
, but/bootstrap/
does. This is a Content Security Policy thing, not a Helmet thing.For the nitty-gritty details, see step 11 of the "Matching Source Expressions" section in the CSP spec:
As an aside, you might want to clean up your Helmet code to something like this:
Your code uses
helmet()
, which includes some default CSP middleware, and then later overrides it withhelmet.contentSecurityPolicy()
. Not a huge deal, but slightly more correct to only use it once.