Respect external URL allow list in vega (#113720)

* Respect external URL allow list in vega

* Add getExternalUrlsAreNotEnabledError

* Revert moving some code in vega_base_view

* Add externalUrl to vega_base_view.d.ts

* Add throwing errors to prevent from following the link

* Fix condition
This commit is contained in:
Diana Derevyankina 2021-10-07 13:11:22 +03:00 committed by GitHub
parent c2049ed754
commit 836abdfc16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 10 deletions

View file

@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
import type { IExternalUrl } from 'kibana/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
import { IServiceSettings } from 'src/plugins/maps_ems/public';
@ -20,6 +21,7 @@ interface VegaViewParams {
filterManager: DataPublicPluginStart['query']['filterManager'];
timefilter: DataPublicPluginStart['query']['timefilter']['timefilter'];
vegaStateRestorer: ReturnType<typeof createVegaStateRestorer>;
externalUrl: IExternalUrl;
}
export class VegaBaseView {

View file

@ -49,6 +49,31 @@ export function bypassExternalUrlCheck(url) {
return { url, bypassToken };
}
const getExternalUrlsAreNotEnabledError = () =>
new Error(
i18n.translate('visTypeVega.vegaParser.baseView.externalUrlsAreNotEnabledErrorMessage', {
defaultMessage:
'External URLs are not enabled. Add {enableExternalUrls} to {kibanaConfigFileName}',
values: {
enableExternalUrls: 'vis_type_vega.enableExternalUrls: true',
kibanaConfigFileName: 'kibana.yml',
},
})
);
const getExternalUrlServiceError = (uri) =>
new Error(
i18n.translate('visTypeVega.vegaParser.baseView.externalUrlServiceErrorMessage', {
defaultMessage:
'External URL [{uri}] was denied by ExternalUrl service. You can configure external URL policies using "{externalUrlPolicy}" setting in {kibanaConfigFileName}.',
values: {
uri,
externalUrlPolicy: 'externalUrl.policy',
kibanaConfigFileName: 'kibana.yml',
},
})
);
export class VegaBaseView {
constructor(opts) {
this._$parentEl = $(opts.parentEl);
@ -62,6 +87,7 @@ export class VegaBaseView {
this._$messages = null;
this._destroyHandlers = [];
this._initialized = false;
this._externalUrl = opts.externalUrl;
this._enableExternalUrls = getEnableExternalUrls();
this._vegaStateRestorer = opts.vegaStateRestorer;
}
@ -165,6 +191,11 @@ export class VegaBaseView {
return idxObj.id;
}
handleExternalUrlError(externalUrlError) {
this.onError(externalUrlError);
throw externalUrlError;
}
createViewConfig() {
const config = {
expr: expressionInterpreter,
@ -180,16 +211,9 @@ export class VegaBaseView {
// because user can only supply pure JSON data structure.
uri = uri.url;
} else if (!this._enableExternalUrls) {
throw new Error(
i18n.translate('visTypeVega.vegaParser.baseView.externalUrlsAreNotEnabledErrorMessage', {
defaultMessage:
'External URLs are not enabled. Add {enableExternalUrls} to {kibanaConfigFileName}',
values: {
enableExternalUrls: 'vis_type_vega.enableExternalUrls: true',
kibanaConfigFileName: 'kibana.yml',
},
})
);
this.handleExternalUrlError(getExternalUrlsAreNotEnabledError());
} else if (!this._externalUrl.validateUrl(uri)) {
this.handleExternalUrlError(getExternalUrlServiceError(uri));
}
const result = await originalSanitize(uri, options);
// This will allow Vega users to load images from any domain.

View file

@ -20,6 +20,7 @@ type VegaVisType = new (el: HTMLDivElement, fireEvent: IInterpreterRenderHandler
};
export const createVegaVisualization = ({
core,
getServiceSettings,
}: VegaVisualizationDependencies): VegaVisType =>
class VegaVisualization {
@ -73,6 +74,7 @@ export const createVegaVisualization = ({
const { filterManager } = this.dataPlugin.query;
const { timefilter } = this.dataPlugin.query.timefilter;
const vegaViewParams = {
externalUrl: core.http.externalUrl,
parentEl: this.el,
fireEvent: this.fireEvent,
vegaStateRestorer: this.vegaStateRestorer,