Skip to content

Commit

Permalink
Update docs, primarily around CSP
Browse files Browse the repository at this point in the history
  • Loading branch information
EvanHahn committed Jun 1, 2024
1 parent 77d574c commit 0710466
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 79 deletions.
30 changes: 7 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,16 @@
# Helmet

Helmet helps secure Express apps by setting HTTP response headers.

## Get started

Here's a sample Express app that uses Helmet:
Help secure Express apps by setting HTTP response headers.

```javascript
import express from "express";
import helmet from "helmet";

const app = express();

// Use Helmet!
app.use(helmet());

app.get("/", (req, res) => {
res.send("Hello world!");
});

app.listen(8000);
```

You can also `require("helmet")` if you prefer.

By default, Helmet sets the following headers:
Helmet sets the following headers by default:

- [`Content-Security-Policy`](#content-security-policy): A powerful allow-list of what can happen on your page which mitigates many attacks
- [`Cross-Origin-Opener-Policy`](#cross-origin-opener-policy): Helps process-isolate your page
Expand All @@ -43,8 +29,7 @@ By default, Helmet sets the following headers:
Each header can be configured. For example, here's how you configure the `Content-Security-Policy` header:

```js
// This sets custom options for the
// Content-Security-Policy header.
// Configure the Content-Security-Policy header.
app.use(
helmet({
contentSecurityPolicy: {
Expand All @@ -59,8 +44,7 @@ app.use(
Headers can also be disabled. For example, here's how you disable the `Content-Security-Policy` and `X-Download-Options` headers:

```js
// This disables the Content-Security-Policy
// and X-Download-Options headers.
// Disable the Content-Security-Policy and X-Download-Options headers
app.use(
helmet({
contentSecurityPolicy: false,
Expand All @@ -82,7 +66,7 @@ Content-Security-Policy: default-src 'self';base-uri 'self';font-src 'self' http

The `Content-Security-Policy` header mitigates a large number of attacks, such as [cross-site scripting][XSS]. See [MDN's introductory article on Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).

This header is powerful but likely requires some configuration.
This header is powerful but likely requires some configuration for your specific app.

To configure this header, pass an object with a nested `directives` object. Each key is a directive name in camel case (such as `defaultSrc`) or kebab case (such as `default-src`). Each value is an array (or other iterable) of strings or functions for that directive. If a function appears in the array, it will be called with the request and response objects.

Expand Down Expand Up @@ -141,7 +125,7 @@ app.use(
);
```

You can get the default directives object with `helmet.contentSecurityPolicy.getDefaultDirectives()`. Here is the default policy (whitespace added for readability):
You can get the default directives object with `helmet.contentSecurityPolicy.getDefaultDirectives()`. Here is the default policy (formatted for readability):

```
default-src 'self';
Expand All @@ -159,7 +143,7 @@ upgrade-insecure-requests

The `default-src` directive can be explicitly disabled by setting its value to `helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc`, but this is not recommended.

You can set the [`Content-Security-Policy-Report-Only`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only) instead.
You can set the [`Content-Security-Policy-Report-Only`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only) instead:

```javascript
// Sets the Content-Security-Policy-Report-Only header
Expand Down
120 changes: 64 additions & 56 deletions middlewares/content-security-policy/README.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,92 @@
# Content Security Policy middleware

Content Security Policy (CSP) helps prevent unwanted content from being injected/loaded into your webpages. This can mitigate cross-site scripting (XSS) vulnerabilities, clickjacking, formjacking, malicious frames, unwanted trackers, and other web client-side attacks.
The `Content-Security-Policy` header mitigates a large number of attacks, such as [cross-site scripting][XSS]. See [MDN's introductory article on Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).

If you want to learn how CSP works, check out the fantastic [HTML5 Rocks guide](https://www.html5rocks.com/en/tutorials/security/content-security-policy/), the [Content Security Policy Reference](https://content-security-policy.com/), and the [Content Security Policy specification](https://www.w3.org/TR/CSP/).
This header is powerful but likely requires some configuration for your specific app.

This middleware helps set Content Security Policies.

Basic usage:
To configure this header, pass an object with a nested `directives` object. Each key is a directive name in camel case (such as `defaultSrc`) or kebab case (such as `default-src`). Each value is an array (or other iterable) of strings or functions for that directive. If a function appears in the array, it will be called with the request and response objects.

```javascript
const contentSecurityPolicy = require("helmet-csp");

// Sets all of the defaults, but overrides `script-src`
// and disables the default `style-src`.
app.use(
contentSecurityPolicy({
useDefaults: true,
directives: {
defaultSrc: ["'self'", "default.example"],
scriptSrc: ["'self'", "js.example.com"],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
"script-src": ["'self'", "example.com"],
"style-src": null,
},
reportOnly: false,
}),
);
```

If no directives are supplied, the following policy is set (whitespace added for readability):

default-src 'self';
base-uri 'self';
font-src 'self' https: data:;
form-action 'self';
frame-ancestors 'self';
img-src 'self' data:;
object-src 'none';
script-src 'self';
script-src-attr 'none';
style-src 'self' https: 'unsafe-inline';
upgrade-insecure-requests

You can use this default with the `useDefaults` option. `useDefaults` is `true` by default.

You can also get the default directives object with `contentSecurityPolicy.getDefaultDirectives()`.

You can set any directives you wish. `defaultSrc` is required, but can be explicitly disabled by setting its value to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`. Directives can be kebab-cased (like `script-src`) or camel-cased (like `scriptSrc`). They are equivalent, but duplicates are not allowed.

The `reportOnly` option, if set to `true`, sets the `Content-Security-Policy-Report-Only` header instead. If you want to set _both_ the normal and `Report-Only` headers, see [this code snippet](https://github.com/helmetjs/helmet/issues/351#issuecomment-1015498560).

This middleware does minimal validation. You should use a more sophisticated CSP validator, like [Google's CSP Evaluator](https://csp-evaluator.withgoogle.com/), to make sure your CSP looks good.

## Recipe: 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");
const contentSecurityPolicy = require("helmet-csp");

// Sets the `script-src` directive to
// "'self' 'nonce-e33cc...'"
// (or similar)
app.use((req, res, next) => {
res.locals.nonce = crypto.randomBytes(32).toString("hex");
res.locals.cspNonce = crypto.randomBytes(32).toString("hex");
next();
});
app.use(
contentSecurityPolicy({
directives: {
scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.cspNonce}'`],
},
}),
);
```

app.use((req, res, next) => {
These directives are merged into a default policy, which you can disable by setting `useDefaults` to `false`.

```javascript
// Sets "Content-Security-Policy: default-src 'self';
// script-src 'self' example.com;object-src 'none';
// upgrade-insecure-requests"
app.use(
contentSecurityPolicy({
useDefaults: true,
useDefaults: false,
directives: {
scriptSrc: ["'self'", `'nonce-${res.locals.nonce}'`],
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "example.com"],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
},
})(req, res, next);
});
}),
);
```

You can get the default directives object with `contentSecurityPolicy.getDefaultDirectives()`. Here is the default policy (formatted for readability):

app.use((req, res) => {
res.end(`<script nonce="${res.locals.nonce}">alert(1 + 1);</script>`);
});
```
default-src 'self';
base-uri 'self';
font-src 'self' https: data:;
form-action 'self';
frame-ancestors 'self';
img-src 'self' data:;
object-src 'none';
script-src 'self';
script-src-attr 'none';
style-src 'self' https: 'unsafe-inline';
upgrade-insecure-requests
```

The `default-src` directive can be explicitly disabled by setting its value to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`, but this is not recommended.

You can set the [`Content-Security-Policy-Report-Only`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only) instead:

## See also
```javascript
// Sets the Content-Security-Policy-Report-Only header
app.use(
contentSecurityPolicy({
directives: {
/* ... */
},
reportOnly: true,
}),
);
```

- [Google's CSP Evaluator tool](https://csp-evaluator.withgoogle.com/)
- [CSP Scanner](https://cspscanner.com/)
- [GitHub's CSP journey](https://githubengineering.com/githubs-csp-journey/)
- [Content Security Policy for Single Page Web Apps](https://developer.squareup.com/blog/content-security-policy-for-single-page-web-apps/)
This module performs very little validation on your CSP. You should rely on CSP checkers like [CSP Evaluator](https://csp-evaluator.withgoogle.com/) instead.

0 comments on commit 0710466

Please sign in to comment.