Next.jsアプリにContent-Security-Policyを設定する
Next.jsアプリのセキュリティ対策の一環としてContent-Security-Policyの設定を行った。
下記記事を参考にさせていただき、Strict CSPを設定。
// pages/_document.tsx
import { randomBytes } from 'crypto'
import Document, { DocumentContext, Head, Html, Main, NextScript } from 'next/document'
import React from 'react'
type WithNonceProp = {
nonce: string
}
export default class MyDocument extends Document<WithNonceProp> {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx)
const nonce = randomBytes(128).toString('base64')
return {
...initialProps,
nonce,
}
}
render() {
const nonce = this.props.nonce
const csp = `object-src 'none'; base-uri 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https: http: 'nonce-${nonce}' 'strict-dynamic'`
return (
<Html>
<Head nonce={nonce}>
<meta httpEquiv="Content-Security-Policy" content={csp} />
</Head>
<body>
<Main />
<NextScript nonce={nonce} />
</body>
</Html>
)
}
}
nonceはリクエストごとに更新すべきたが、ISR(Incremental Static Regeneration)のアプリなので次回の更新までは同じnonceになってしまう。
SSRにする予定は今のところないのと、何も対策しないよりは良いだろうということでnonceがしばらくキャッシュされてしまうのは許容することにした。