diff --git a/Common/Server/Utils/VM/VMRunner.ts b/Common/Server/Utils/VM/VMRunner.ts index a63b2925b6..b3f394a606 100644 --- a/Common/Server/Utils/VM/VMRunner.ts +++ b/Common/Server/Utils/VM/VMRunner.ts @@ -22,6 +22,14 @@ const BLOCKED_SANDBOX_PROPERTIES: ReadonlySet = new Set([ "__proto__", "prototype", "mainModule", + // Block Playwright methods that can spawn processes or access internals. + // Prevents RCE via browser.browserType().launch({executablePath:"/bin/sh"}) + // and traversal via page.context().browser().browserType().launch(...) + "browserType", // Browser → BrowserType (which has launch/connect) + "launch", // BrowserType.launch() spawns a child process + "launchPersistentContext", // BrowserType.launchPersistentContext() spawns a child process + "connectOverCDP", // BrowserType.connectOverCDP() connects via Chrome DevTools Protocol + "newCDPSession", // BrowserContext/Page.newCDPSession() opens raw CDP sessions ]); /** diff --git a/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts b/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts index cb62d83b19..734d15d0c1 100644 --- a/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts +++ b/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts @@ -153,13 +153,14 @@ export default class SyntheticMonitor { ); } + // Only expose `page` to the sandbox — never the `browser` object. + // Exposing `browser` allows RCE via browser.browserType().launch({executablePath:"/bin/sh"}). result = await VMRunner.runCodeInNodeVM({ code: options.script, options: { timeout: PROBE_SYNTHETIC_MONITOR_SCRIPT_TIMEOUT_IN_MS, args: {}, context: { - browser: browserSession.browser, page: browserSession.page, screenSizeType: options.screenSizeType, browserType: options.browserType,