feat(vue-renderer): add csp option for csp v1 compatibility (#5975)

This commit is contained in:
William Chong 2019-06-26 23:22:45 +08:00 committed by Xin Du (Clark)
parent 79877b4ec3
commit cf39c75711
4 changed files with 56 additions and 1 deletions

View File

@ -220,6 +220,7 @@ export function getNuxtConfig(_options) {
allowedSources: undefined, allowedSources: undefined,
policies: undefined, policies: undefined,
addMeta: Boolean(options._generate), addMeta: Boolean(options._generate),
unsafeInlineCompatiblity: false,
reportOnly: options.debug reportOnly: options.debug
}) })
} }

View File

@ -92,6 +92,7 @@ describe('config: options', () => {
expect(csp).toEqual({ expect(csp).toEqual({
hashAlgorithm: 'sha256', hashAlgorithm: 'sha256',
addMeta: false, addMeta: false,
unsafeInlineCompatiblity: false,
allowedSources: true, allowedSources: true,
policies: undefined, policies: undefined,
reportOnly: false, reportOnly: false,

View File

@ -121,7 +121,7 @@ export default class SSRRenderer extends BaseRenderer {
if (csp) { if (csp) {
// 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)
const containsUnsafeInlineScriptSrc = csp.policies && csp.policies['script-src'] && csp.policies['script-src'].includes(`'unsafe-inline'`) const containsUnsafeInlineScriptSrc = csp.policies && csp.policies['script-src'] && csp.policies['script-src'].includes(`'unsafe-inline'`)
if (!containsUnsafeInlineScriptSrc) { if (csp.unsafeInlineCompatiblity || !containsUnsafeInlineScriptSrc) {
const hash = crypto.createHash(csp.hashAlgorithm) const hash = crypto.createHash(csp.hashAlgorithm)
hash.update(serializedSession) hash.update(serializedSession)
cspScriptSrcHashes.push(`'${csp.hashAlgorithm}-${hash.digest('base64')}'`) cspScriptSrcHashes.push(`'${csp.hashAlgorithm}-${hash.digest('base64')}'`)

View File

@ -196,7 +196,34 @@ describe('basic ssr csp', () => {
expect(headers[cspHeader]).toMatch(/script-src 'self' 'unsafe-inline'$/) expect(headers[cspHeader]).toMatch(/script-src 'self' 'unsafe-inline'$/)
} }
) )
test(
'Contain hash and \'unsafe-inline\' when unsafeInlineCompatiblity is enabled',
async () => {
const policies = {
'script-src': [`'unsafe-inline'`]
}
nuxt = await startCspServer({
unsafeInlineCompatiblity: true,
policies
}) })
for (let i = 0; i < 5; i++) {
await rp(url('/stateless'), {
resolveWithFullResponse: true
})
}
const { headers } = await rp(url('/stateful'), {
resolveWithFullResponse: true
})
expect(headers[cspHeader]).toMatch(/script-src 'sha256-.*' 'self' 'unsafe-inline'$/)
}
)
})
describe('debug mode', () => { describe('debug mode', () => {
test( test(
'Not contain Content-Security-Policy-Report-Only header, when csp is false', 'Not contain Content-Security-Policy-Report-Only header, when csp is false',
@ -390,5 +417,31 @@ describe('basic ssr csp', () => {
expect(headers[reportOnlyHeader]).toMatch(/script-src 'self' 'unsafe-inline'$/) expect(headers[reportOnlyHeader]).toMatch(/script-src 'self' 'unsafe-inline'$/)
} }
) )
test(
'Contain hash and \'unsafe-inline\' when unsafeInlineCompatiblity is enabled',
async () => {
const policies = {
'script-src': [`'unsafe-inline'`]
}
nuxt = await startCspServer({
unsafeInlineCompatiblity: true,
policies
})
for (let i = 0; i < 5; i++) {
await rp(url('/stateless'), {
resolveWithFullResponse: true
})
}
const { headers } = await rp(url('/stateful'), {
resolveWithFullResponse: true
})
expect(headers[cspHeader]).toMatch(/script-src 'sha256-.*' 'self' 'unsafe-inline'$/)
}
)
}) })
}) })