diff --git a/lib/common/options.js b/lib/common/options.js index e685efe2a2..94135539f4 100755 --- a/lib/common/options.js +++ b/lib/common/options.js @@ -315,7 +315,8 @@ Options.defaults = { csp: { enabled: false, hashAlgorithm: 'sha256', - allowedSources: [] + allowedSources: undefined, + policies: undefined } }, watchers: { diff --git a/lib/core/middleware/nuxt.js b/lib/core/middleware/nuxt.js index bc80a99bcf..81643a0820 100644 --- a/lib/core/middleware/nuxt.js +++ b/lib/core/middleware/nuxt.js @@ -68,12 +68,31 @@ module.exports = async function nuxtMiddleware(req, res, next) { } if (this.options.render.csp && this.options.render.csp.enabled) { - const allowedSources = cspScriptSrcHashes.concat(this.options.render.csp.allowedSources) + const allowedSources = this.options.render.csp.allowedSources + const policies = {...{}, ...this.options.render.csp.policies} + let cspStr = `script-src 'self' ${(cspScriptSrcHashes).join(' ')}` + if (Array.isArray(allowedSources)) { + // For compatible section + cspStr = `script-src 'self' ${cspScriptSrcHashes.concat(allowedSources).join(' ')}` + } else if (typeof policies === 'object' && policies !== null && !Array.isArray(policies)) { + // Set default policy if necessary + if (!policies['script-src'] || !Array.isArray(policies['script-src'])) { + policies['script-src'] = [`'self'`].concat(cspScriptSrcHashes) + } else { + policies['script-src'] = cspScriptSrcHashes.concat(policies['script-src']) + if (!policies['script-src'].includes(`'self'`)) { + policies['script-src'] = [`'self'`].concat(policies['script-src']) + } + } - res.setHeader( - 'Content-Security-Policy', - `script-src 'self' ${(allowedSources).join(' ')}` - ) + // Make content-security-policy string + let cspArr = [] + Object.keys(policies).forEach((k) => { + cspArr.push(`${k} ${policies[k].join(' ')}`) + }) + cspStr = cspArr.join('; ') + } + res.setHeader('Content-Security-Policy', cspStr) } // Send response