helmet-csp
    Overview
    Documentation
    Insights
    Code
    Contributors
    Dependencies
    Alternatives

helmet-csp

Content Security Policy middleware.

2.9.1  •  Published 3 months ago  •  by helmetjs  •  MIT License

Content Security Policy middleware

Build Status

Content Security Policy helps prevent unwanted content being injected into your webpages; this can mitigate cross-site scripting (XSS) vulnerabilities, malicious frames, unwanted trackers, and more. If you want to learn how CSP works, check out the fantastic HTML5 Rocks guide, the Content Security Policy Reference, and the Content Security Policy specification. This module helps set Content Security Policies.

Usage:

const csp = require('helmet-csp')

app.use(csp({
  // Specify directives as normal.
  directives: {
    defaultSrc: ["'self'", 'default.com'],
    scriptSrc: ["'self'", "'unsafe-inline'"],
    styleSrc: ['style.com'],
    fontSrc: ["'self'", 'fonts.com'],
    imgSrc: ['img.com', 'data:'],
    sandbox: ['allow-forms', 'allow-scripts'],
    reportUri: '/report-violation',
    objectSrc: ["'none'"],
    upgradeInsecureRequests: true,
    workerSrc: false  // This is not set.
  },

  // This module will detect common mistakes in your directives and throw errors
  // if it finds any. To disable this, enable "loose mode".
  loose: false,

  // Set to true if you only want browsers to report errors, not block them.
  // You may also set this to a function(req, res) in order to decide dynamically
  // whether to use reportOnly mode, e.g., to allow for a dynamic kill switch.
  reportOnly: false,

  // Set to true if you want to blindly set all headers: Content-Security-Policy,
  // X-WebKit-CSP, and X-Content-Security-Policy.
  setAllHeaders: false,

  // Set to true if you want to disable CSP on Android where it can be buggy.
  disableAndroid: false,

  // Set to false if you want to completely disable any user-agent sniffing.
  // This may make the headers less compatible but it will be much faster.
  // This defaults to `true`.
  browserSniff: true
}))

There are a lot of inconsistencies in how browsers implement CSP. Helmet looks at the user-agent of the browser and sets the appropriate header and value for that browser. If no user-agent is matched, it will set all the headers with the 2.0 spec.

Supported directives

Directives can be kebab-cased (like script-src) or camel-cased (like scriptSrc); they are equivalent.

The following directives are supported:

  • base-uri or baseUri
  • block-all-mixed-content or blockAllMixedContent
  • child-src or childSrc
  • connect-src or connectSrc
  • default-src or defaultSrc
  • font-src or fontSrc
  • form-action or formAction
  • frame-ancestors or frameAncestors
  • frame-src or frameSrc
  • img-src or imgSrc
  • manifest-src or manifestSrc
  • media-src or mediaSrc
  • object-src or objectSrc
  • plugin-types or pluginTypes
  • prefetch-src or prefetchSrc
  • report-to or reportTo
  • report-uri or reportUri
  • require-sri-for or requireSriFor
  • sandbox or sandbox
  • script-src or scriptSrc
  • style-src or styleSrc
  • upgrade-insecure-requests or upgradeInsecureRequests
  • worker-src or workerSrc

Handling CSP violations

If you’ve specified a reportUri, browsers will POST any CSP violations to your server. Here’s a simple example of a route that handles those reports:

// You need a JSON parser first.
app.use(bodyParser.json({
  type: ['json', 'application/csp-report']
}))

app.post('/report-violation', (req, res) => {
  if (req.body) {
    console.log('CSP Violation: ', req.body)
  } else {
    console.log('CSP Violation: No data received!')
  }
  res.status(204).end()
})

Not all browsers send CSP violations in the same way, so this might require a little work.

Note: If you’re using a CSRF module like csurf, you might have problems handling these violations without a valid CSRF token. The fix is to put your CSP report route above csurf middleware.

Generating nonces

You can dynamically generate nonces to allow inline <script> tags to be safely evaluated. Here’s a simple example:

const crypto = require('crypto')

app.use(function (req, res, next) {
  res.locals.nonce = crypto.randomBytes(16).toString('hex')
  next()
})

app.use(csp({
  directives: {
    scriptSrc: [
      "'self'",
      (req, res) => `'nonce-${res.locals.nonce}'`  // 'nonce-348c18b14aaf3e00938d8bdd613f1149'
    ]
  }
}))

app.use((req, res) => {
  res.end(`<script nonce="${res.locals.nonce}">alert(1 + 1);</script>`)
})

Using CSP with a CDN

The default behavior of CSP is generate headers tailored for the browser that’s requesting your page. If you have a CDN in front of your application, the CDN may cache the wrong headers, rendering your CSP useless. Make sure to eschew a CDN when using this module or set the browserSniff option to false.

See also

How do you feel about the name Devstore for this site?

Popularity

Weekly Downloads
644.7K
Stars
203

Maintenance

Development

Last ver 3 months ago
Created 5 years ago
Last commit 1 month ago
8 days between commits

Technology

Node version: 12.9.1
32.8K unpacked

Compliance

MIT License
OSI Approved
0 vulnerabilities

Contributors

20 contributors
Evan Hahn
Maintainer, 223 commits, 23 merges, 4 PRs
Works at Airtable
teppeis
5 commits, 2 PRs
Works at cybozu / kintone
Nicholas Clawson
3 commits, 3 PRs
Works at facebook
Matthew Finifter
3 commits, 1 PRs
Dan Stroot
2 commits, 1 PRs
Indospace.io
2 commits, 2 PRs
Works at Indospace.io

Tags

helmet
security
express
connect
content
policy
csp
xss
Ready for the next level?
Join Devstore's founding team to help us build the ultimate open-source app store, work with the latest technologies, and enjoy great culture, impact and autonomy
© 2019 Devstore, Inc.
Devstore helps developers find and use open-source packages, so they can focus on building amazing things