OneUptime: OS Command Injection in Probe NetworkPathMonitor via unsanitized destination in traceroute exec()
Description
OneUptime is a solution for monitoring and managing online services. Prior to version 10.0.7, an OS command injection vulnerability in NetworkPathMonitor.performTraceroute() allows any authenticated project user to execute arbitrary operating system commands on the Probe server by injecting shell metacharacters into a monitor's destination field. Version 10.0.7 fixes the vulnerability.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
An OS command injection in OneUptime's NetworkPathMonitor allows any authenticated user to execute arbitrary commands on the Probe server via crafted monitor destinations.
Root
Cause
In OneUptime versions prior to 10.0.7, the NetworkPathMonitor.performTraceroute() method constructs shell commands by directly interpolating user-controlled destination input into a string template. The destination value, originating from the public trace() method without validation or sanitization, is passed to child_process.exec() [1]. Because exec() spawns a shell, any shell metacharacters (such as ;, |, $(), backticks, or &&) in the destination field will be interpreted, enabling injection [1].
Attack
Surface
Any authenticated project user can exploit this vulnerability by providing a malicious destination string when creating or updating a monitor. No special privileges beyond standard project access are required [1][3]. The injection occurs on the Probe server, which executes the traceroute command with the unsanitized input [1].
Impact
Successful exploitation allows an attacker to execute arbitrary OS commands on the Probe server, potentially compromising the monitoring infrastructure, accessing sensitive data, or using the server as a pivot point for further attacks [1][3].
Mitigation
Version 10.0.7 fixes the vulnerability by replacing child_process.exec() with execFile(), which does not invoke a shell, and by adding input validation (function isValidDestination()`) that restricts destination to safe hostnames and IP addresses [1][4]. Users are strongly recommended to upgrade immediately [1][3].
AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@oneuptime/commonnpm | < 10.0.7 | 10.0.7 |
Affected products
2- OneUptime/oneuptimev5Range: < 10.0.7
Patches
1f2cce35a04fafeat: enhance NetworkPathMonitor with destination validation and execFile usage
1 file changed · +45 −9
Probe/Utils/Monitors/MonitorTypes/NetworkPathMonitor.ts+45 −9 modified@@ -10,11 +10,12 @@ import NetworkPathTrace, { } from "Common/Types/Monitor/NetworkMonitor/NetworkPathTrace"; import dns from "dns"; import { promisify } from "util"; -import { exec } from "child_process"; +import { execFile } from "child_process"; -const execAsync: ( - command: string, -) => Promise<{ stdout: string; stderr: string }> = promisify(exec); +const execFileAsync: ( + file: string, + args: string[], +) => Promise<{ stdout: string; stderr: string }> = promisify(execFile); const dnsResolve: (hostname: string) => Promise<string[]> = promisify( dns.resolve, ); @@ -83,6 +84,24 @@ export default class NetworkPathMonitor { return ipv4Pattern.test(address) || ipv6Pattern.test(address); } + /** + * Validates that a destination string is a safe hostname or IP address + */ + private static isValidDestination(destination: string): boolean { + if (!destination || destination.length === 0 || destination.length > 253) { + return false; + } + + // Allow valid IP addresses + if (this.isIPAddress(destination)) { + return true; + } + + // Validate as hostname: only alphanumeric, hyphens, and dots allowed + const hostnamePattern: RegExp = /^[a-zA-Z0-9]([a-zA-Z0-9\-.]*[a-zA-Z0-9])?$/; + return hostnamePattern.test(destination); + } + /** * Performs DNS lookup for a hostname */ @@ -162,18 +181,35 @@ export default class NetworkPathMonitor { }; try { + // Validate destination to prevent command injection + if (!this.isValidDestination(destination)) { + throw new Error( + `Invalid destination: ${destination}. Must be a valid hostname or IP address.`, + ); + } + // Use the appropriate traceroute command based on OS const isMac: boolean = process.platform === "darwin"; const isWindows: boolean = process.platform === "win32"; - let command: string; + let cmd: string; + let args: string[]; if (isWindows) { - command = `tracert -h ${maxHops} -w ${Math.ceil(timeout / 1000) * 1000} ${destination}`; + cmd = "tracert"; + args = [ + "-h", + maxHops.toString(), + "-w", + (Math.ceil(timeout / 1000) * 1000).toString(), + destination, + ]; } else if (isMac) { - command = `traceroute -m ${maxHops} -w 3 ${destination}`; + cmd = "traceroute"; + args = ["-m", maxHops.toString(), "-w", "3", destination]; } else { // Linux - command = `traceroute -m ${maxHops} -w 3 ${destination}`; + cmd = "traceroute"; + args = ["-m", maxHops.toString(), "-w", "3", destination]; } const timeoutPromise: Promise<never> = new Promise( @@ -188,7 +224,7 @@ export default class NetworkPathMonitor { ); const tracePromise: Promise<{ stdout: string; stderr: string }> = - execAsync(command); + execFileAsync(cmd, args); const { stdout } = await Promise.race([tracePromise, timeoutPromise]);
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-jmhp-5558-qxh5ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-27728ghsaADVISORY
- github.com/OneUptime/oneuptime/commit/f2cce35a04fac756cecc7a4c55e23758b99288c1ghsax_refsource_MISCWEB
- github.com/OneUptime/oneuptime/security/advisories/GHSA-jmhp-5558-qxh5ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.