From 67510766816fdf6824ffdda504d7186980c2ff15 Mon Sep 17 00:00:00 2001 From: Miki Date: Sat, 10 Sep 2022 14:45:49 -0700 Subject: [PATCH] Use a forced CSP-compliant interpreter with Vega visualizations * Pass `options` to `vega.parse` to enable inclusion of parsed ASTs * Introduce the forced CSP-compliant interpreter that prevents evaluation of unsafe methods * Modified the consumed `leaflet-vega` package to one that honors `options` Signed-off-by: Miki --- package.json | 5 +++-- src/plugins/vis_type_vega/public/lib/vega.js | 3 ++- .../public/vega_view/vega_base_view.js | 5 ++++- .../vis_type_vega/public/vega_view/vega_map_view.js | 1 + .../vis_type_vega/public/vega_view/vega_view.js | 5 ++++- yarn.lock | 13 +++++++++---- 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index eaf3265fe01..ca1243d3bb6 100644 --- a/package.json +++ b/package.json @@ -393,7 +393,7 @@ "leaflet": "1.5.1", "leaflet-draw": "0.4.14", "leaflet-responsive-popup": "0.6.4", - "leaflet-vega": "^0.8.6", + "leaflet-vega": "npm:@amoo-miki/leaflet-vega@0.8.8", "leaflet.heat": "0.2.0", "less": "^4.1.2", "license-checker": "^16.0.0", @@ -445,6 +445,7 @@ "typescript": "4.0.2", "ui-select": "0.19.8", "vega": "^5.17.3", + "vega-interpreter": "npm:@amoo-miki/vega-forced-csp-compliant-interpreter@1.0.6", "vega-lite": "^4.16.8", "vega-schema-url-parser": "^2.1.0", "vega-tooltip": "^0.24.2", @@ -457,4 +458,4 @@ "node": "14.20.0", "yarn": "^1.21.1" } -} \ No newline at end of file +} diff --git a/src/plugins/vis_type_vega/public/lib/vega.js b/src/plugins/vis_type_vega/public/lib/vega.js index 73d1af5d30a..1c3068bae9e 100644 --- a/src/plugins/vis_type_vega/public/lib/vega.js +++ b/src/plugins/vis_type_vega/public/lib/vega.js @@ -30,5 +30,6 @@ import * as vegaLite from 'vega-lite/build-es5/vega-lite'; import * as vega from 'vega/build-es5/vega'; +import { expressionInterpreter as vegaExpressionInterpreter } from 'vega-interpreter/build/vega-interpreter.module'; -export { vega, vegaLite }; +export { vega, vegaLite, vegaExpressionInterpreter }; diff --git a/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js b/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js index 82411911046..1286495af90 100644 --- a/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js +++ b/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js @@ -31,7 +31,7 @@ import $ from 'jquery'; import moment from 'moment'; import dateMath from '@elastic/datemath'; -import { vega, vegaLite } from '../lib/vega'; +import { vega, vegaLite, vegaExpressionInterpreter } from '../lib/vega'; import { Utils } from '../data_model/utils'; import { euiPaletteColorBlind } from '@elastic/eui'; import { i18n } from '@osd/i18n'; @@ -79,6 +79,7 @@ export class VegaBaseView { this._timefilter = opts.timefilter; this._view = null; this._vegaViewConfig = null; + this._vegaViewOptions = null; this._$messages = null; this._destroyHandlers = []; this._initialized = false; @@ -130,6 +131,7 @@ export class VegaBaseView { }); this._vegaViewConfig = this.createViewConfig(); + this._vegaViewOptions = { ast: true }; // The derived class should create this method await this._initViewCustomizations(); @@ -185,6 +187,7 @@ export class VegaBaseView { // eslint-disable-next-line import/namespace logLevel: vega.Warn, // note: eslint has a false positive here renderer: this._parser.renderer, + expr: vegaExpressionInterpreter, }; // Override URL sanitizer to prevent external data loading (if disabled) diff --git a/src/plugins/vis_type_vega/public/vega_view/vega_map_view.js b/src/plugins/vis_type_vega/public/vega_view/vega_map_view.js index c1919631d12..6f0a961f7a6 100644 --- a/src/plugins/vis_type_vega/public/vega_view/vega_map_view.js +++ b/src/plugins/vis_type_vega/public/vega_view/vega_map_view.js @@ -144,6 +144,7 @@ export class VegaMapView extends VegaBaseView { bindingsContainer: this._$controls.get(0), delayRepaint: mapConfig.delayRepaint, viewConfig: this._vegaViewConfig, + viewOptions: this._vegaViewOptions, onWarning: this.onWarn.bind(this), onError: this.onError.bind(this), }, diff --git a/src/plugins/vis_type_vega/public/vega_view/vega_view.js b/src/plugins/vis_type_vega/public/vega_view/vega_view.js index 50119439f68..45d15849ed4 100644 --- a/src/plugins/vis_type_vega/public/vega_view/vega_view.js +++ b/src/plugins/vis_type_vega/public/vega_view/vega_view.js @@ -36,7 +36,10 @@ export class VegaView extends VegaBaseView { // In some cases, Vega may be initialized twice... TBD if (!this._$container) return; - const view = new vega.View(vega.parse(this._parser.spec), this._vegaViewConfig); + const view = new vega.View( + vega.parse(this._parser.spec, null, this._vegaViewOptions), + this._vegaViewConfig + ); view.warn = this.onWarn.bind(this); view.error = this.onError.bind(this); diff --git a/yarn.lock b/yarn.lock index 6f378118a6a..66060020065 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11628,10 +11628,10 @@ leaflet-responsive-popup@0.6.4: resolved "https://registry.yarnpkg.com/leaflet-responsive-popup/-/leaflet-responsive-popup-0.6.4.tgz#b93d9368ef9f96d6dc911cf5b96d90e08601c6b3" integrity sha512-2D8G9aQA6NHkulDBPN9kqbUCkCpWQQ6dF0xFL11AuEIWIbsL4UC/ZPP5m8GYM0dpU6YTlmyyCh1Tz+cls5Q4dg== -leaflet-vega@^0.8.6: - version "0.8.6" - resolved "https://registry.yarnpkg.com/leaflet-vega/-/leaflet-vega-0.8.6.tgz#dd4090a6123cb983c2b732d53ec9e4daa53736b2" - integrity sha1-3UCQphI8uYPCtzLVPsnk2qU3NrI= +"leaflet-vega@npm:@amoo-miki/leaflet-vega@0.8.7": + version "0.8.7" + resolved "https://registry.yarnpkg.com/@amoo-miki/leaflet-vega/-/leaflet-vega-0.8.7.tgz#8faca1b4b8e2ef7d48667ac6faad9204f4da7153" + integrity sha512-T4M5yziwj3Fi9Adsbce+cdWqPjON0BRwEjwqLlPMoirU1vhifA6YKrlZkVzJrK0IIm+hdfMCLkBz33gD8fdxzQ== dependencies: vega-spec-injector "^0.0.2" @@ -17988,6 +17988,11 @@ vega-hierarchy@~4.1.0: vega-dataflow "^5.7.3" vega-util "^1.15.2" +"vega-interpreter@npm:@amoo-miki/vega-forced-csp-compliant-interpreter@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@amoo-miki/vega-forced-csp-compliant-interpreter/-/vega-forced-csp-compliant-interpreter-1.0.5.tgz#49970be9b00ca7e45ced0617fbf373c77a28aab4" + integrity sha512-lfeU77lVoUbSCC6N1ywdKg+I6K08xpkd82TLon+LebtKyC8aLCe7P5Dd/89zAPyFwRyobKftHu8z0xpV7R7a4Q== + vega-label@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/vega-label/-/vega-label-1.2.0.tgz#bcb2659aec54f890f9debab3e41ab87a58292dce"