diff --git a/src/legacy/server/csp/index.test.ts b/src/legacy/server/csp/index.test.ts index 9586166b65641..c11c3cd2d6e1b 100644 --- a/src/legacy/server/csp/index.test.ts +++ b/src/legacy/server/csp/index.test.ts @@ -39,12 +39,13 @@ import { // the nature of a change in defaults during a PR review. test('default CSP rules', () => { expect(DEFAULT_CSP_RULES).toMatchInlineSnapshot(` -Array [ - "script-src 'unsafe-eval' 'nonce-{nonce}'", - "worker-src blob:", - "child-src blob:", -] -`); + Array [ + "script-src 'unsafe-eval' 'nonce-{nonce}'", + "worker-src blob:", + "child-src blob:", + "style-src 'unsafe-inline' 'self'", + ] + `); }); test('CSP strict mode defaults to disabled', () => { diff --git a/src/legacy/server/csp/index.ts b/src/legacy/server/csp/index.ts index 96c359e61e25b..d0b626e3fa2cc 100644 --- a/src/legacy/server/csp/index.ts +++ b/src/legacy/server/csp/index.ts @@ -26,6 +26,7 @@ export const DEFAULT_CSP_RULES = Object.freeze([ `script-src 'unsafe-eval' 'nonce-{nonce}'`, 'worker-src blob:', 'child-src blob:', + `style-src 'unsafe-inline' 'self'`, ]); export const DEFAULT_CSP_STRICT = false; diff --git a/test/api_integration/apis/general/csp.js b/test/api_integration/apis/general/csp.js index f3501aa55adaa..8c28d7e6d7dd9 100644 --- a/test/api_integration/apis/general/csp.js +++ b/test/api_integration/apis/general/csp.js @@ -27,13 +27,27 @@ export default function ({ getService }) { const response = await supertest.get('/app/kibana'); expect(response.headers).to.have.property('content-security-policy'); - }); + const header = response.headers['content-security-policy']; + const parsed = new Map(header.split(';').map(rule => { + const parts = rule.trim().split(' '); + const key = parts.splice(0, 1)[0]; + return [key, parts]; + })); - it('csp header does not allow all inline scripts', async () => { - const response = await supertest.get('/app/kibana'); + // ensure script-src uses a nonce, and remove it so we can .eql everything else + const scriptSrc = parsed.get('script-src'); + expect(scriptSrc).to.be.an(Array); + const nonceIndex = scriptSrc.findIndex(value => value.startsWith(`'nonce-`)); + expect(nonceIndex).greaterThan(-1); + scriptSrc.splice(nonceIndex, 1); - expect(response.headers['content-security-policy']).to.contain('script-src'); - expect(response.headers['content-security-policy']).not.to.contain('unsafe-inline'); + const entries = Array.from(parsed.entries()); + expect(entries).to.eql([ + [ 'script-src', [ '\'unsafe-eval\'' ] ], + [ 'worker-src', [ 'blob:' ] ], + [ 'child-src', [ 'blob:' ] ], + [ 'style-src', [ '\'unsafe-inline\'', '\'self\'' ] ] + ]); }); }); } diff --git a/x-pack/test/oidc_api_integration/apis/implicit_flow/oidc_auth.ts b/x-pack/test/oidc_api_integration/apis/implicit_flow/oidc_auth.ts index 613f10054fd84..4d377f974b845 100644 --- a/x-pack/test/oidc_api_integration/apis/implicit_flow/oidc_auth.ts +++ b/x-pack/test/oidc_api_integration/apis/implicit_flow/oidc_auth.ts @@ -53,7 +53,7 @@ export default function({ getService }: FtrProviderContext) { expect(response.headers['content-type']).to.be('text/html; charset=utf-8'); expect(response.headers['cache-control']).to.be('private, no-cache, no-store'); expect(response.headers['content-security-policy']).to.be( - `script-src 'unsafe-eval' 'nonce-${scriptNonce}'; worker-src blob:; child-src blob:` + `script-src 'unsafe-eval' 'nonce-${scriptNonce}'; worker-src blob:; child-src blob:; style-src 'unsafe-inline' 'self'` ); // Check that script that forwards URL fragment worked correctly.