Change default value of csp.disableUnsafeEval to 'true' (#150157)

This change ensures that the `unsafe-eval` source expression isn't included in
the Kibana Content Security Policy (CSP) by default.

Users can set `csp.disableUnsafeEval: false` to reintroduce `unsafe-eval`.
However, since this config option is deprecated as of this commit, it's
recommended to instead set `csp.script_src: ['unsafe-eval']`.

Closes #150156
This commit is contained in:
Thomas Watson 2023-02-07 13:07:13 +01:00 committed by GitHub
parent a496623003
commit 50444bbd59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 9 additions and 61 deletions

View file

@ -26,11 +26,11 @@ Set to `false` to disable Console. *Default: `true`*
Add sources for the https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src[Content Security Policy `script-src` directive].
`csp.disableUnsafeEval`::
experimental[] Set this to `true` to remove the https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_eval_expressions[`unsafe-eval`] source expression from the `script-src` directive. *Default: `false`*
deprecated:[8.7.0,Use `csp.script_src: ['unsafe-eval']` instead if you wish to enable `unsafe-eval`. This config option will have no effect in a future version.] Set this to `false` to add the https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_eval_expressions[`unsafe-eval`] source expression to the `script-src` directive. *Default: `true`*
+
By enabling `csp.disableUnsafeEval`, Kibana will use a custom version of the Handlebars template library.
When `csp.disableUnsafeEval` is set to `true`, Kibana will use a custom version of the Handlebars template library.
Handlebars is used in various locations in the Kibana frontend where custom templates can be supplied by the user when for instance setting up a visualisation.
If you experience any issues rendering Handlebars templates after turning on `csp.disableUnsafeEval`, please revert this setting to `false` and https://github.com/elastic/kibana/issues/new/choose[open an issue] in the Kibana GitHub repository.
If you experience any issues rendering Handlebars templates, please set this setting to `false` and https://github.com/elastic/kibana/issues/new/choose[open an issue] in the Kibana GitHub repository.
`csp.worker_src`::
Add sources for the https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/worker-src[Content Security Policy `worker-src` directive].

View file

@ -39,13 +39,7 @@ const getDirectiveValueValidator = ({ allowNone, allowNonce }: DirectiveValidati
const configSchema = schema.object(
{
disableUnsafeEval: schema.conditional(
// Default disableUnsafeEval to false if it's not a distributable release
schema.contextRef('dist'),
true,
schema.boolean({ defaultValue: false }),
schema.boolean({ defaultValue: true })
),
disableUnsafeEval: schema.boolean({ defaultValue: true }),
script_src: schema.arrayOf(schema.string(), {
defaultValue: [],
validate: getDirectiveValidator({ allowNone: false, allowNonce: false }),

View file

@ -1,25 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { schema } from '@kbn/config-schema';
import { cspConfig } from './config';
const origSchema = cspConfig.schema;
export const mockConfig = {
create(defaultDisableUnsafeEval: boolean) {
// @ts-expect-error: Property 'extends' does not exist on type??
cspConfig.schema = cspConfig.schema.extends({
disableUnsafeEval: schema.boolean({ defaultValue: defaultDisableUnsafeEval }),
});
return cspConfig;
},
reset() {
cspConfig.schema = origSchema;
},
};

View file

@ -8,7 +8,6 @@
import { CspConfig } from './csp_config';
import { cspConfig, CspConfigType } from './config';
import { mockConfig } from './csp_config.test.mocks';
// CSP rules aren't strictly additive, so any change can potentially expand or
// restrict the policy in a way we consider a breaking change. For that reason,
@ -34,6 +33,7 @@ describe('CspConfig', () => {
expect(CspConfig.DEFAULT).toMatchInlineSnapshot(`
CspConfig {
"disableEmbedding": false,
"disableUnsafeEval": true,
"header": "script-src 'self'; worker-src blob: 'self'; style-src 'unsafe-inline' 'self'",
"strict": true,
"warnLegacyBrowsers": true,
@ -140,36 +140,15 @@ describe('CspConfig', () => {
);
});
test('when "disableUnsafeEval" is not set, and the default value is "false", the `unsafe-eval` CSP should be set', () => {
// The default value for `disableUnsafeEval` depends on whether Kibana is a distributable or not. To test both scenarios, we mock the config.
const mockedConfig = mockConfig.create(false).schema.validate({});
test('when "disableUnsafeEval" is not set, the `unsafe-eval` CSP should not be set', () => {
const config = new CspConfig({
...mockedConfig,
script_src: ['foo', 'bar'],
});
expect(config.header).toEqual(
`script-src 'self' 'unsafe-eval' foo bar; worker-src blob: 'self'; style-src 'unsafe-inline' 'self'`
);
mockConfig.reset();
});
test('when "disableUnsafeEval" is not set, and the default value is "true", the `unsafe-eval` CSP should not be set', () => {
// The default value for `disableUnsafeEval` depends on whether Kibana is a distributable or not. To test both scenarios, we mock the config.
const mockedConfig = mockConfig.create(true).schema.validate({});
const config = new CspConfig({
...mockedConfig,
...defaultConfig,
script_src: ['foo', 'bar'],
});
expect(config.header).toEqual(
`script-src 'self' foo bar; worker-src blob: 'self'; style-src 'unsafe-inline' 'self'`
);
mockConfig.reset();
});
});

View file

@ -21,6 +21,7 @@ export class CspConfig implements ICspConfig {
readonly #directives: CspDirectives;
public readonly strict: boolean;
public readonly disableUnsafeEval: boolean;
public readonly warnLegacyBrowsers: boolean;
public readonly disableEmbedding: boolean;
public readonly header: string;
@ -37,6 +38,7 @@ export class CspConfig implements ICspConfig {
}
this.header = this.#directives.getCspHeader();
this.strict = rawCspConfig.strict;
this.disableUnsafeEval = rawCspConfig.disableUnsafeEval;
this.warnLegacyBrowsers = rawCspConfig.warnLegacyBrowsers;
this.disableEmbedding = rawCspConfig.disableEmbedding;
}

View file

@ -24,7 +24,6 @@ describe('csp collector', () => {
function updateCsp(config: Partial<ICspConfig>) {
httpMock.csp = new CspConfig({
...CspConfig.DEFAULT,
disableUnsafeEval: false,
style_src: [],
worker_src: [],
script_src: [],

View file

@ -43,7 +43,6 @@ export default function () {
// Needed for async search functional tests to introduce a delay
`--data.search.aggs.shardDelay.enabled=true`,
`--security.showInsecureClusterWarning=false`,
'--csp.disableUnsafeEval=true',
'--telemetry.banner=false',
'--telemetry.optIn=false',
// These are *very* important to have them pointing to staging