patternjavascriptMajor
Content-Security-Policy Header Setup
Viewed 0 times
cspcontent security policyhelmetnonceunsafe-inlinedefault-srcxss prevention
Error Messages
Problem
Without a Content-Security-Policy header, browsers allow scripts, styles, and other resources to load from any origin, making reflected or stored XSS attacks far more impactful.
Solution
Define a strict CSP using the helmet npm package. Start with default-src 'self' and incrementally add trusted external sources only as needed.
Why
CSP is a browser-enforced allowlist for resources. Even if an attacker injects a script reference, the browser refuses to load it if the source is not in the policy.
Gotchas
- 'unsafe-inline' for scripts defeats most of the protection CSP provides—use nonces instead
- Use Content-Security-Policy-Report-Only first to audit violations before enforcing
- Hash-based CSP for inline scripts breaks when script content changes
- Third-party widgets and ad networks often require 'unsafe-inline'; isolate them in sandboxed iframes instead
Code Snippets
Strict CSP with nonce via helmet
const helmet = require('helmet');
const crypto = require('crypto');
app.use((req, res, next) => {
res.locals.nonce = crypto.randomBytes(16).toString('base64');
next();
});
app.use((req, res, next) => {
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.nonce}'`],
styleSrc: ["'self'", 'https://fonts.googleapis.com'],
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'"],
fontSrc: ["'self'", 'https://fonts.gstatic.com'],
objectSrc: ["'none'"],
frameAncestors: ["'none'"]
}
})(req, res, next);
});Revisions (0)
No revisions yet.