From fe87f7e5fb241f569afd786dceacc00bec37c1f3 Mon Sep 17 00:00:00 2001 From: jackkav Date: Fri, 31 Jul 2026 08:23:49 +0200 Subject: [PATCH] =?UTF-8?q?feat(templating):=20(T1)=20Preferences=20UI=20?= =?UTF-8?q?=E2=80=94=20plugin-sandbox=20toggle=20+=20per-plugin=20elevated?= =?UTF-8?q?=20+=20mode=20indicator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Scripting settings: new "Sandbox all plugin code (experimental)" toggle for pluginSandboxEnabled (data-testid toggle-plugin-sandbox), beside the existing template-tag toggle. - Plugins settings: each user plugin card now shows its resolved execution mode (Sandboxed / Elevated / In-process, data-testid plugin-mode-) and a "Full host access" checkbox (data-testid plugin-elevated-) that writes pluginConfig..elevated. Mode + toggle read from live settings so they update immediately, before the plugin list reloads. - Widened SerializablePlugin.config to carry the optional `elevated` flag through the bridge. --- .../src/common/plugins/bridge-types.ts | 2 +- .../src/ui/components/settings/plugins.tsx | 61 +++++++++++++++++++ .../settings/scripting-settings.tsx | 24 ++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/packages/insomnia/src/common/plugins/bridge-types.ts b/packages/insomnia/src/common/plugins/bridge-types.ts index 05fc474f2b..3c5f8e04fc 100644 --- a/packages/insomnia/src/common/plugins/bridge-types.ts +++ b/packages/insomnia/src/common/plugins/bridge-types.ts @@ -76,7 +76,7 @@ export interface SerializablePlugin { description: string; version: string; directory: string; - config: { disabled: boolean }; + config: { disabled: boolean; elevated?: boolean }; /** Parsed `insomnia.permissions` manifest (sandbox plan C3), surfaced in Preferences → Plugins. */ permissions: { modules: string[]; capabilities: string[] }; /** Validation warnings from parsing `permissions`; shown on the plugin card. Empty when clean. */ diff --git a/packages/insomnia/src/ui/components/settings/plugins.tsx b/packages/insomnia/src/ui/components/settings/plugins.tsx index 914ebaa31b..8c44de2394 100644 --- a/packages/insomnia/src/ui/components/settings/plugins.tsx +++ b/packages/insomnia/src/ui/components/settings/plugins.tsx @@ -13,6 +13,7 @@ import { } from 'react-aria-components'; import type { SerializablePlugin } from '~/common/plugins/bridge-types'; +import { resolvePluginExecutionMode } from '~/common/plugins/sandbox-mode'; import { validatePluginName } from '~/common/utils/plugin-name'; import { useRootLoaderData } from '~/root'; import { plugins as pluginsBridge } from '~/ui/plugins/renderer-bridge'; @@ -498,6 +499,28 @@ export const Plugins: FC = () => { ? 'Declared empty permissions (baseline access)' : 'No permissions declared (baseline access)'; + // T1: this plugin's resolved execution mode + the per-plugin "elevated" escape hatch. + // Only user plugins reach this list (bundle plugins are filtered out above). Read + // `elevated` from live settings (not the load-time plugin.config snapshot) so the toggle + // and badge update immediately, before the plugin list reloads. + const isElevated = settings.pluginConfig?.[plugin.name]?.elevated === true; + const executionMode = resolvePluginExecutionMode(settings, { + directory: plugin.directory, + config: { elevated: isElevated }, + }); + const modeLabel = + executionMode === 'sandboxed' + ? 'Sandboxed' + : executionMode === 'elevated' + ? 'Elevated' + : 'In-process'; + const modeTitle = + executionMode === 'sandboxed' + ? 'Runs in the QuickJS sandbox (default-deny host access).' + : executionMode === 'elevated' + ? 'Runs in the main process with full host access (you granted this).' + : 'Sandbox is off — runs in the main process with full host access.'; + return ( { > {permissionLabel} + + {modeLabel} + {plugin.permissionWarnings && plugin.permissionWarnings.length > 0 && ( {
+ { + patchSettings({ + pluginConfig: { + ...settings.pluginConfig, + [plugin.name]: { + ...plugin.config, + ...settings.pluginConfig?.[plugin.name], + elevated: isSelected, + }, + }, + }); + }} + > +
+ +
+ + Full host access + +
{plugin.version} diff --git a/packages/insomnia/src/ui/components/settings/scripting-settings.tsx b/packages/insomnia/src/ui/components/settings/scripting-settings.tsx index 413b288246..a1075f5ee1 100644 --- a/packages/insomnia/src/ui/components/settings/scripting-settings.tsx +++ b/packages/insomnia/src/ui/components/settings/scripting-settings.tsx @@ -144,6 +144,7 @@ export const ScriptingSettings = () => { const sandboxEnabled = settings.scriptSandboxEnabled !== false; const strictModeEnabled = settings.scriptStrictModeEnabled !== false; const templateTagSandboxEnabled = settings.templateTagSandboxEnabled === true; + const pluginSandboxEnabled = settings.pluginSandboxEnabled === true; const disabledRules = settings.disabledSecurityRules ?? []; const disabledProperties = settings.disabledBlockedProperties ?? []; const disabledRoots = settings.disabledBlockedRoots ?? []; @@ -340,6 +341,29 @@ export const ScriptingSettings = () => {
+
+
+
+ Sandbox all plugin code (experimental) +

+ Run every untrusted plugin surface — template tags, request/response hooks, actions, and load-time code — + inside the QuickJS-WASM sandbox. Installed plugins are default-deny; grant an individual plugin full host + access with "Run with full host access" in Preferences → Plugins. +

+
+ patchSettings({ pluginSandboxEnabled: enabled })} + className="group flex items-center gap-2" + > +
+ +
+
+
+
+