Issue
I deployed a simple portfolio site on Heroku (free tier). The site is built with Express Node.js and React for frontend. To use my .dev domain which requires SSL, I signed up for Cloudflare. Now everything works except my sending email form. I get the following error:
Refused to connect to `https://<my-app>.herokuapp.com/api/v1/email/sendemail' because it violates the following Contect Security Policy directive: "default-src 'self'". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
I figured out it’s something with helmet and CSP policies, but I don’t understand what exactly I need to put in there.
As a temporary solution I disabled CSP like this:
app.use(
helmet({
contentSecurityPolicy: false,
})
);
But ideally I want to do something like this:
app.use(
helmet({
contentSecurityPolicy: {
directives: {
...helmet.contentSecurityPolicy.getDefaultDirectives(),
'connect-src': ["'self'", 'cdnjs.cloudflare.com'],
},
},
})
);
But I don’t know what to put in there. Neither cdnjs.cloudflare.com nor ajax.cloudflare.com work.
Solution
Here are most common usages with CSP in Express. This is configuration of my app, I think you should find there everything you need:
app.use(
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
blockAllMixedContent: [],
fontSrc: ["'self'", 'https:', 'data:'],
frameAncestors: ["'self'", 'https://accounts.google.com/'],
frameSrc: ["'self'", 'https://accounts.google.com/'],
imgSrc: ["'self'", 'data:'],
objectSrc: ["'self'", 'blob:'],
mediaSrc: ["'self'", 'blob:', 'data:'],
scriptSrc: ["'self'", 'https://apis.google.com'],
scriptSrcAttr: ["'none'"],
styleSrc: ["'self'", 'https:', "'unsafe-inline'"],
upgradeInsecureRequests: [],
connectSrc: ["'self'", 'https://my-app.herokuapp.com'],
},
},
})
);
Your connectSrc
should include https://my-app.herokuapp.com
, just like you see on last line.