From 5549cd7a76037a936f5c3195216626ea5f030878 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Mon, 9 Oct 2023 10:42:38 +0200 Subject: [PATCH] Sandbox: Fix `history.replace` calls inside the sandbox (#76049) * Sandbox: Fix `history.replace` calls inside the sandbox * Improve signature verification and comments * Add clarifying comment --- .../plugins/sandbox/distortion_map.ts | 33 +++++++++++++++---- .../plugins/sandbox/sandbox_plugin_loader.ts | 15 ++++++--- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/public/app/features/plugins/sandbox/distortion_map.ts b/public/app/features/plugins/sandbox/distortion_map.ts index d74a85ab86e..eeb6fd756ff 100644 --- a/public/app/features/plugins/sandbox/distortion_map.ts +++ b/public/app/features/plugins/sandbox/distortion_map.ts @@ -1,3 +1,4 @@ +import { ProxyTarget } from '@locker/near-membrane-shared'; import { cloneDeep, isFunction } from 'lodash'; import { PluginMeta } from '@grafana/data'; @@ -520,13 +521,31 @@ async function distortPostMessage(distortions: DistortionMap) { } /** - * We define "live" APIs as APIs that can only be distorted in runtime on-the-fly and not at initialization - * time like other distortions do. - * - * This could be because the objects we want to patch only become available after specific states are reached - * or because the libraries we want to patch are lazy-loaded and we don't have access to their definitions - * + * "Live" APIs are APIs that can only be distorted at runtime. + * This could be because the objects we want to patch only become available after specific states are reached, + * or because the libraries we want to patch are lazy-loaded and we don't have access to their definitions. + * We put here only distortions that can't be static because they are dynamicly loaded */ -export async function distortLiveApis() { +export function distortLiveApis(originalValue: ProxyTarget): ProxyTarget | undefined { distortMonacoEditor(generalDistortionMap); + + // This distorts the `history.replace` function in react-router-dom. + // constructed for each browser history and is only accessible within the react context. + // Note that this distortion does not affect `String.prototype.replace` calls. + // because they don't go through distortions + if ( + originalValue instanceof Function && + originalValue.name === 'replace' && + originalValue.prototype.constructor.length === 2 + ) { + return function replace(this: unknown, ...args: unknown[]) { + // validate history.replace signature further + if (args && args[0] && typeof args[0] === 'string' && args[1] && !(args[1] instanceof Function)) { + const newArgs = cloneDeep(args); + return Reflect.apply(originalValue, this, newArgs); + } + return Reflect.apply(originalValue, this, args); + }; + } + return; } diff --git a/public/app/features/plugins/sandbox/sandbox_plugin_loader.ts b/public/app/features/plugins/sandbox/sandbox_plugin_loader.ts index bad44d9a273..c6884d816b6 100644 --- a/public/app/features/plugins/sandbox/sandbox_plugin_loader.ts +++ b/public/app/features/plugins/sandbox/sandbox_plugin_loader.ts @@ -63,10 +63,17 @@ async function doImportPluginModuleInSandbox(meta: PluginMeta): Promise