mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Use nonce attribute for all scripts and preloads if provided (#4539)
When implementing a strict CSP with nonces and `strict-dynamic`, every script and preload requires a nonce. https://csp.withgoogle.com/docs/strict-csp.html
This commit is contained in:
parent
17e410a1d0
commit
1c817d2bbf
|
@ -39,6 +39,10 @@ export class Head extends Component {
|
|||
_documentProps: PropTypes.any
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
nonce: PropTypes.string
|
||||
}
|
||||
|
||||
getChunkPreloadLink (filename) {
|
||||
const { __NEXT_DATA__, buildManifest } = this.context._documentProps
|
||||
let { assetPrefix, buildId } = __NEXT_DATA__
|
||||
|
@ -48,6 +52,7 @@ export class Head extends Component {
|
|||
return files.map(file => {
|
||||
return <link
|
||||
key={filename}
|
||||
nonce={this.props.nonce}
|
||||
rel='preload'
|
||||
href={`${assetPrefix}/_next/${file}`}
|
||||
as='script'
|
||||
|
@ -79,6 +84,7 @@ export class Head extends Component {
|
|||
rel='preload'
|
||||
href={`${assetPrefix}/_next/webpack/chunks/${chunk}`}
|
||||
as='script'
|
||||
nonce={this.props.nonce}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
@ -90,9 +96,9 @@ export class Head extends Component {
|
|||
|
||||
return <head {...this.props}>
|
||||
{(head || []).map((h, i) => React.cloneElement(h, { key: h.key || i }))}
|
||||
{page !== '/_error' && <link rel='preload' href={`${assetPrefix}/_next/${buildId}/page${pagePathname}`} as='script' />}
|
||||
<link rel='preload' href={`${assetPrefix}/_next/${buildId}/page/_app.js`} as='script' />
|
||||
<link rel='preload' href={`${assetPrefix}/_next/${buildId}/page/_error.js`} as='script' />
|
||||
{page !== '/_error' && <link rel='preload' href={`${assetPrefix}/_next/${buildId}/page${pagePathname}`} as='script' nonce={this.props.nonce} />}
|
||||
<link rel='preload' href={`${assetPrefix}/_next/${buildId}/page/_app.js`} as='script' nonce={this.props.nonce} />
|
||||
<link rel='preload' href={`${assetPrefix}/_next/${buildId}/page/_error.js`} as='script' nonce={this.props.nonce} />
|
||||
{this.getPreloadDynamicChunks()}
|
||||
{this.getPreloadMainLinks()}
|
||||
{styles || null}
|
||||
|
@ -136,6 +142,7 @@ export class NextScript extends Component {
|
|||
<script
|
||||
key={filename}
|
||||
src={`${assetPrefix}/_next/${file}`}
|
||||
nonce={this.props.nonce}
|
||||
{...additionalProps}
|
||||
/>
|
||||
))
|
||||
|
@ -165,6 +172,7 @@ export class NextScript extends Component {
|
|||
async
|
||||
key={chunk}
|
||||
src={`${assetPrefix}/_next/webpack/chunks/${chunk}`}
|
||||
nonce={this.props.nonce}
|
||||
/>
|
||||
))}
|
||||
</Fragment>
|
||||
|
@ -204,9 +212,9 @@ export class NextScript extends Component {
|
|||
`}
|
||||
`
|
||||
}} />}
|
||||
{page !== '/_error' && <script async id={`__NEXT_PAGE__${pathname}`} src={`${assetPrefix}/_next/${buildId}/page${pagePathname}`} />}
|
||||
<script async id={`__NEXT_PAGE__/_app`} src={`${assetPrefix}/_next/${buildId}/page/_app.js`} />
|
||||
<script async id={`__NEXT_PAGE__/_error`} src={`${assetPrefix}/_next/${buildId}/page/_error.js`} />
|
||||
{page !== '/_error' && <script async id={`__NEXT_PAGE__${pathname}`} src={`${assetPrefix}/_next/${buildId}/page${pagePathname}`} nonce={this.props.nonce} />}
|
||||
<script async id={`__NEXT_PAGE__/_app`} src={`${assetPrefix}/_next/${buildId}/page/_app.js`} nonce={this.props.nonce} />
|
||||
<script async id={`__NEXT_PAGE__/_error`} src={`${assetPrefix}/_next/${buildId}/page/_error.js`} nonce={this.props.nonce} />
|
||||
{staticMarkup ? null : this.getDynamicChunks()}
|
||||
{staticMarkup ? null : this.getScripts()}
|
||||
</Fragment>
|
||||
|
|
|
@ -9,14 +9,14 @@ export default class MyDocument extends Document {
|
|||
render () {
|
||||
return (
|
||||
<html>
|
||||
<Head>
|
||||
<Head nonce='test-nonce'>
|
||||
<style>{`body { margin: 0 } /* custom! */`}</style>
|
||||
</Head>
|
||||
<body className='custom_class'>
|
||||
<p id='custom-property'>{this.props.customProperty}</p>
|
||||
<p id='document-hmr'>Hello Document HMR</p>
|
||||
<Main />
|
||||
<NextScript />
|
||||
<NextScript nonce='test-nonce' />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
|
|
|
@ -24,6 +24,16 @@ export default function ({ app }, suiteName, render, fetch) {
|
|||
const $ = await get$('/')
|
||||
expect($('#custom-property').text() === 'Hello Document')
|
||||
})
|
||||
|
||||
test('It adds nonces to all scripts and preload links', async () => {
|
||||
const $ = await get$('/')
|
||||
const nonce = 'test-nonce'
|
||||
let noncesAdded = true
|
||||
$('script, link[rel=preload]').each((index, element) => {
|
||||
if ($(element).attr('nonce') !== nonce) noncesAdded = false
|
||||
})
|
||||
expect(noncesAdded).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('_app', () => {
|
||||
|
|
Loading…
Reference in a new issue