Skip to content

Commit 5d819bb

Browse files
committed
feat: add support for CSP nonce
1 parent 5454a03 commit 5d819bb

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

.circleci/config.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: 2
1+
version: 2.1
22
jobs:
33
build:
44
docker:
@@ -36,3 +36,10 @@ jobs:
3636
- run:
3737
name: release
3838
command: yarn run semantic-release || true
39+
workflows:
40+
build-and-deploy:
41+
jobs:
42+
- build:
43+
context:
44+
- github-release
45+
- npm-release

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,13 @@ const html = (
122122
</html>
123123
)
124124
```
125+
126+
## Content Security Policy
127+
128+
Make sure your header includes this meta tag:
129+
130+
```jsx
131+
<meta property="csp-nonce" content={nonce} />
132+
```
133+
134+
And in SSR, pass the `nonce` to `registry.scriptTags({ nonce })`.

src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ export class ScriptsRegistry {
2929
results: { [src: string]: { error: ?Error } } = {}
3030
promises: { [src: string]: Promise<any> } = {}
3131

32-
scriptTags(): React.Node {
33-
return this.scripts.map(props => <script key={props.src} {...props} />)
32+
scriptTags(options?: {| nonce?: string |}): React.Node {
33+
return this.scripts.map(props => <script key={props.src} nonce={options ? options.nonce : undefined} {...props} />)
3434
}
3535
}
3636

src/loadScript.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
/* eslint-env browser */
33
import { type InnerProps } from './index'
44

5+
let nonce
6+
function getNonce(): string | void {
7+
if (nonce === undefined) {
8+
const node = document.querySelector('meta[property="csp-nonce"], meta[name="csp-nonce"]')
9+
nonce = node ? node.getAttribute('content') ?? null : null
10+
}
11+
return nonce
12+
}
13+
514
const loadScript = async ({
615
scriptsRegistry,
716
onLoad,
@@ -29,6 +38,7 @@ const loadScript = async ({
2938
return new Promise((resolve: () => void, reject: (error?: Error) => void) => {
3039
const script = document.createElement('script')
3140
script.src = src
41+
script.nonce = getNonce()
3242
Object.keys(props).forEach(key => script.setAttribute(key, props[key]))
3343
script.onload = resolve
3444
script.onerror = reject

0 commit comments

Comments
 (0)