From f6a739438ec7ec160d5b274f598e50213522067d Mon Sep 17 00:00:00 2001 From: dinex-dev Date: Fri, 17 Jul 2026 13:29:18 +0530 Subject: [PATCH] =?UTF-8?q?feat(security):=20RQ-2426=20=E2=80=94=20Develop?= =?UTF-8?q?er=20Script=20Mode=20preference=20+=20proxy=20wiring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the desktop `devScriptMode` user preference and threads it into the proxy so "code" rules run sandboxed by default, with an opt-in full-access dev mode. - userPreference schema/types + GET/UPDATE_DEV_SCRIPT_MODE actions (fail-safe: only an explicit boolean/"true" enables it). - getDevScriptMode() → threaded into proxyConfig in startProxyServer. - storage-cache applies it live on the running proxy (no restart), mirroring allowInsecureCerts. Pairs with requestly-proxy RQ-2426 (safe/dev modes) and the interceptor web toggle. Co-Authored-By: Claude Opus 4.8 --- .../action-processors/user-preference.ts | 18 ++++++++++++++++++ .../storage/schemas/userPreferenceSchema.ts | 8 ++++++++ src/lib/storage/types/action-types.ts | 5 +++++ src/lib/storage/types/user-preference.ts | 2 ++ src/renderer/actions/proxy/startProxyServer.ts | 5 ++++- src/renderer/actions/storage/cacheUtils.ts | 7 +++++++ src/renderer/services/storage-cache.ts | 8 +++++++- 7 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/lib/storage/action-processors/user-preference.ts b/src/lib/storage/action-processors/user-preference.ts index 91673a0..8436cdf 100644 --- a/src/lib/storage/action-processors/user-preference.ts +++ b/src/lib/storage/action-processors/user-preference.ts @@ -51,6 +51,24 @@ class UserPreferenceActionProcessor extends BaseActionProcessor { this.store.set({ allowInsecureCerts: value }) break; } + case USER_PREFERENCE.GET_DEV_SCRIPT_MODE: + return !!this.store.get("devScriptMode") + case USER_PREFERENCE.UPDATE_DEV_SCRIPT_MODE: { + // RQ-2426: fail SAFE. Dev mode (full host access for code rules) is enabled + // only for an explicit boolean `true`, or a recognized truthy boolean-string + // (IPC may serialize booleans). A missing key, object, or unknown value stays + // `false` (safe QuickJS sandbox). + // @ts-ignore + const raw = payload?.data?.devScriptMode; + let value = false; + if (typeof raw === "boolean") { + value = raw; + } else if (typeof raw === "string") { + value = raw === "true" || raw === "1"; + } + this.store.set({ devScriptMode: value }) + break; + } case USER_PREFERENCE.GET_COMPLETE_LOGGING_CONFIG: return this.store.get("localFileLogConfig") diff --git a/src/lib/storage/schemas/userPreferenceSchema.ts b/src/lib/storage/schemas/userPreferenceSchema.ts index c9834ed..26b684e 100644 --- a/src/lib/storage/schemas/userPreferenceSchema.ts +++ b/src/lib/storage/schemas/userPreferenceSchema.ts @@ -13,6 +13,14 @@ export const userPreferenceSchema = { default: false }, + // RQ-2426: when true, "code" rules run via the legacy full-access executor + // (DEV mode) instead of the safe QuickJS sandbox. Full system access — off + // (safe) by default. + devScriptMode: { + type: "boolean", + default: false + }, + localFileLogConfig: { type: "object", properties: { diff --git a/src/lib/storage/types/action-types.ts b/src/lib/storage/types/action-types.ts index 5b19190..a57fa7a 100644 --- a/src/lib/storage/types/action-types.ts +++ b/src/lib/storage/types/action-types.ts @@ -26,6 +26,11 @@ export enum USER_PREFERENCE { GET_ALLOW_INSECURE_CERTS = "USER_PREFERENCE:GET_ALLOW_INSECURE_CERTS", UPDATE_ALLOW_INSECURE_CERTS = "USER_PREFERENCE:UPDATE_ALLOW_INSECURE_CERTS", + // RQ-2426: DEV script-execution mode (full host access for code rules). Off (safe + // QuickJS sandbox) by default. + GET_DEV_SCRIPT_MODE = "USER_PREFERENCE:GET_DEV_SCRIPT_MODE", + UPDATE_DEV_SCRIPT_MODE = "USER_PREFERENCE:UPDATE_DEV_SCRIPT_MODE", + GET_COMPLETE_LOGGING_CONFIG = "USER_PREFERENCE:LOCAL_LOG_FILE:GET_ALL", GET_IS_LOGGING_ENABLED = "USER_PREFERENCE:LOCAL_LOG_FILE:GET_IS_ENABLED", diff --git a/src/lib/storage/types/user-preference.ts b/src/lib/storage/types/user-preference.ts index 0d5831d..2f2a232 100644 --- a/src/lib/storage/types/user-preference.ts +++ b/src/lib/storage/types/user-preference.ts @@ -1,6 +1,7 @@ export interface UserPreferenceObj { defaultPort: number; allowInsecureCerts?: boolean; + devScriptMode?: boolean; localFileLogConfig: { isEnabled: boolean; storePath: string; @@ -11,6 +12,7 @@ export interface UserPreferenceObj { export interface ISource { defaultPort: number; allowInsecureCerts?: boolean; + devScriptMode?: boolean; isLocalLoggingEnabled: boolean; logStorePath: string; localLogFilterfilter: string[] diff --git a/src/renderer/actions/proxy/startProxyServer.ts b/src/renderer/actions/proxy/startProxyServer.ts index f63aff5..cca5273 100644 --- a/src/renderer/actions/proxy/startProxyServer.ts +++ b/src/renderer/actions/proxy/startProxyServer.ts @@ -11,7 +11,7 @@ import { staticConfig } from "../../config"; import * as Sentry from "@sentry/browser"; import startHelperServer, { stopHelperServer } from "../startHelperServer"; import logger from "utils/logger"; -import { getDefaultProxyPort, getAllowInsecureCerts } from "../storage/cacheUtils"; +import { getDefaultProxyPort, getAllowInsecureCerts, getDevScriptMode } from "../storage/cacheUtils"; import { handleCARegeneration } from "../apps/os/ca/utils"; import { startHelperSocketServer, stopHelperSocketServer } from "../helperSocketServer"; import portfinder from "portfinder"; @@ -46,6 +46,9 @@ function startProxyFromModule(PROXY_PORT: number) { // RQ-2425: user-controlled toggle for upstream TLS verification. // Defaults to false (verify) unless the user enabled insecure requests. allowInsecureCerts: getAllowInsecureCerts(), + // RQ-2426: DEV script-execution mode for code rules. Defaults to false + // (safe QuickJS sandbox) unless the user explicitly opted into full access. + devScriptMode: getDevScriptMode(), }; RQProxyProvider.createInstance( proxyConfig, diff --git a/src/renderer/actions/storage/cacheUtils.ts b/src/renderer/actions/storage/cacheUtils.ts index 3346b0a..00d4629 100644 --- a/src/renderer/actions/storage/cacheUtils.ts +++ b/src/renderer/actions/storage/cacheUtils.ts @@ -16,6 +16,13 @@ export const getAllowInsecureCerts = (): boolean => { return !!userPreferences.getConfig()?.allowInsecureCerts; } +// RQ-2426: true only when the user has explicitly opted into DEV script mode +// (full host access for code rules). Defaults to false (safe sandbox). +export const getDevScriptMode = (): boolean => { + const userPreferences = new UserPreferenceFetcher(); + return userPreferences.getConfig()?.devScriptMode === true; +} + export const getLocalFileLogConfig = () => { const userPreferences = new UserPreferenceFetcher(); const { localFileLogConfig }= userPreferences.getConfig() diff --git a/src/renderer/services/storage-cache.ts b/src/renderer/services/storage-cache.ts index 55c8a13..6683607 100644 --- a/src/renderer/services/storage-cache.ts +++ b/src/renderer/services/storage-cache.ts @@ -46,8 +46,14 @@ class StorageCacheService { rqProxy.setAllowInsecureCerts(!!newUserPreferences?.allowInsecureCerts); appliedLive = true; } + // RQ-2426: apply the DEV script-mode toggle live on the running proxy too. + // Only an explicit `true` enables it (full host access); anything else is + // the safe sandbox. + if (rqProxy?.setDevScriptMode) { + rqProxy.setDevScriptMode(newUserPreferences?.devScriptMode === true); + } } catch (e) { - console.log("Failed to apply allowInsecureCerts live", e); + console.log("Failed to apply allowInsecureCerts/devScriptMode live", e); } // Restart the proxy only when the port actually changed (or as a fallback