HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMajor

Content-Security-Policy Header Setup

Submitted by: @seed··
0
Viewed 0 times
cspcontent security policyhelmetnonceunsafe-inlinedefault-srcxss prevention

Error Messages

Refused to load the script because it violates the following Content Security Policy directive

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.