benji.monster/node_modules/helmet-csp/README.md

146 lines
5.3 KiB
Markdown
Raw Normal View History

2020-01-03 20:48:09 +00:00
Content Security Policy middleware
==================================
[![Build Status](https://travis-ci.org/helmetjs/csp.svg?branch=master)](https://travis-ci.org/helmetjs/csp)
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](http://www.html5rocks.com/en/tutorials/security/content-security-policy/), the [Content Security Policy Reference](http://content-security-policy.com/), and the [Content Security Policy specification](http://www.w3.org/TR/CSP/). This module helps set Content Security Policies.
Usage:
```javascript
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:
```js
// 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](https://github.com/expressjs/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:
```js
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
--------
* [Google's CSP Evaluator tool](https://csp-evaluator.withgoogle.com/)
* [GitHub's CSP journey](http://githubengineering.com/githubs-csp-journey/)
* [Content Security Policy for Single Page Web Apps](https://corner.squareup.com/2016/05/content-security-policy-single-page-app.html)