mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-27 08:02:01 +00:00
feat(vue-renderer): add csp meta tags (#5354)
This commit is contained in:
parent
57a673d95f
commit
b978a3761d
@ -3,7 +3,6 @@ import fs from 'fs'
|
|||||||
import defaultsDeep from 'lodash/defaultsDeep'
|
import defaultsDeep from 'lodash/defaultsDeep'
|
||||||
import defaults from 'lodash/defaults'
|
import defaults from 'lodash/defaults'
|
||||||
import pick from 'lodash/pick'
|
import pick from 'lodash/pick'
|
||||||
import isObject from 'lodash/isObject'
|
|
||||||
import uniq from 'lodash/uniq'
|
import uniq from 'lodash/uniq'
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
import { guardDir, isNonEmptyString, isPureObject, isUrl, getMainModule } from '@nuxt/utils'
|
import { guardDir, isNonEmptyString, isPureObject, isUrl, getMainModule } from '@nuxt/utils'
|
||||||
@ -179,16 +178,14 @@ export function getNuxtConfig(_options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply default hash to CSP option
|
// Apply default hash to CSP option
|
||||||
const { csp } = options.render
|
if (options.render.csp) {
|
||||||
|
options.render.csp = defaults({}, options.render.csp, {
|
||||||
const cspDefaults = {
|
|
||||||
hashAlgorithm: 'sha256',
|
hashAlgorithm: 'sha256',
|
||||||
allowedSources: undefined,
|
allowedSources: undefined,
|
||||||
policies: undefined,
|
policies: undefined,
|
||||||
|
addMeta: Boolean(options._generate),
|
||||||
reportOnly: options.debug
|
reportOnly: options.debug
|
||||||
}
|
})
|
||||||
if (csp) {
|
|
||||||
options.render.csp = defaults(isObject(csp) ? csp : {}, cspDefaults)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cssSourceMap
|
// cssSourceMap
|
||||||
|
@ -81,6 +81,7 @@ describe('config: options', () => {
|
|||||||
const { render: { csp } } = getNuxtConfig({ render: { csp: { allowedSources: true, test: true } } })
|
const { render: { csp } } = getNuxtConfig({ render: { csp: { allowedSources: true, test: true } } })
|
||||||
expect(csp).toEqual({
|
expect(csp).toEqual({
|
||||||
hashAlgorithm: 'sha256',
|
hashAlgorithm: 'sha256',
|
||||||
|
addMeta: false,
|
||||||
allowedSources: true,
|
allowedSources: true,
|
||||||
policies: undefined,
|
policies: undefined,
|
||||||
reportOnly: false,
|
reportOnly: false,
|
||||||
|
@ -407,21 +407,26 @@ export default class VueRenderer {
|
|||||||
APP += `<script>${serializedSession}</script>`
|
APP += `<script>${serializedSession}</script>`
|
||||||
|
|
||||||
// Calculate CSP hashes
|
// Calculate CSP hashes
|
||||||
|
const { csp } = this.context.options.render
|
||||||
const cspScriptSrcHashes = []
|
const cspScriptSrcHashes = []
|
||||||
const csp = this.context.options.render.csp
|
if (csp) {
|
||||||
const containsUnsafeInlineScriptSrc = csp && csp.policies && csp.policies['script-src'] && csp.policies['script-src'].includes(`'unsafe-inline'`)
|
|
||||||
|
|
||||||
// Only add the hash if 'unsafe-inline' rule isn't present to avoid conflicts (#5387)
|
// Only add the hash if 'unsafe-inline' rule isn't present to avoid conflicts (#5387)
|
||||||
if (csp && !containsUnsafeInlineScriptSrc) {
|
const containsUnsafeInlineScriptSrc = csp.policies && csp.policies['script-src'] && csp.policies['script-src'].includes(`'unsafe-inline'`)
|
||||||
const { hashAlgorithm } = this.context.options.render.csp
|
if (!containsUnsafeInlineScriptSrc) {
|
||||||
const hash = crypto.createHash(hashAlgorithm)
|
const hash = crypto.createHash(csp.hashAlgorithm)
|
||||||
hash.update(serializedSession)
|
hash.update(serializedSession)
|
||||||
cspScriptSrcHashes.push(`'${hashAlgorithm}-${hash.digest('base64')}'`)
|
cspScriptSrcHashes.push(`'${csp.hashAlgorithm}-${hash.digest('base64')}'`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call ssr:csp hook
|
// Call ssr:csp hook
|
||||||
await this.context.nuxt.callHook('vue-renderer:ssr:csp', cspScriptSrcHashes)
|
await this.context.nuxt.callHook('vue-renderer:ssr:csp', cspScriptSrcHashes)
|
||||||
|
|
||||||
|
// Add csp meta tags
|
||||||
|
if (csp.addMeta) {
|
||||||
|
HEAD += `<meta http-equiv="Content-Security-Policy" content="script-src ${cspScriptSrcHashes.join()}">`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prepend scripts
|
// Prepend scripts
|
||||||
APP += this.renderScripts(context)
|
APP += this.renderScripts(context)
|
||||||
APP += m.script.text({ body: true })
|
APP += m.script.text({ body: true })
|
||||||
|
Loading…
Reference in New Issue
Block a user