Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-46339

CVE-2026-46339: 9Router AI Router RCE Vulnerability

CVE-2026-46339 is a remote code execution flaw in 9Router AI Router that allows unauthenticated attackers to execute arbitrary commands. This post covers the technical details, affected versions 0.4.30-0.4.37, and mitigation.

Published:

CVE-2026-46339 Overview

CVE-2026-46339 is a critical unauthenticated command injection vulnerability affecting 9Router, an AI router and token saver. The flaw resides in the src/proxy.js middleware, which failed to protect the /api/cli-tools/* and /api/mcp/* routes. Unauthenticated attackers can register arbitrary customPlugins through src/app/api/cli-tools/cowork-settings/route.js and execute commands through the Model Context Protocol (MCP) bridge. Versions 0.4.30 through 0.4.36 are affected, and the issue is resolved in 0.4.37. The vulnerability is classified under [CWE-78] (OS Command Injection).

Critical Impact

Unauthenticated attackers can achieve arbitrary command execution on the host running 9Router by registering malicious plugins through unprotected API routes.

Affected Products

  • 9Router versions 0.4.30 through 0.4.36
  • Component: src/proxy.js middleware
  • Component: src/app/api/cli-tools/cowork-settings/route.js

Discovery Timeline

  • 2026-07-15 - CVE-2026-46339 published to NVD
  • 2026-07-16 - Last updated in NVD database

Technical Details for CVE-2026-46339

Vulnerability Analysis

The vulnerability stems from missing authentication and authorization checks in the 9Router proxy middleware. The src/proxy.js middleware did not include /api/cli-tools/* or /api/mcp/* in its protected route list. This allowed unauthenticated network attackers to reach sensitive endpoints that spawn child processes and register plugins.

An attacker can send a crafted request to the cowork-settings endpoint to register a customPlugin entry. The MCP bridge then executes commands defined by that plugin, resulting in arbitrary OS command execution on the host. The EPSS score of 4.572% (90.55 percentile) reflects a meaningful likelihood of exploitation activity relative to other published CVEs.

Root Cause

Two distinct defects combine to produce the impact. First, the proxy authentication layer omitted the CLI tools and MCP route prefixes, leaving them publicly reachable. Second, the plugin registration route accepted arbitrary command definitions without validating them against an allowlist of MCP commands.

Attack Vector

The attack is network-reachable, requires no privileges, and requires no user interaction. An attacker sends an HTTP request to /api/cli-tools/cowork-settings to install a plugin, then triggers execution through the MCP bridge at /api/mcp/.

javascript
// Security patch in src/app/api/cli-tools/cowork-settings/route.js
 import path from "path";
 import os from "os";
 import crypto from "crypto";
-import { DEFAULT_PLUGINS, LOCAL_STDIO_PLUGINS, buildManagedMcpServers } from "@/shared/constants/coworkPlugins";
+import { DEFAULT_PLUGINS, LOCAL_STDIO_PLUGINS, ALLOWED_MCP_COMMANDS, buildManagedMcpServers } from "@/shared/constants/coworkPlugins";
 import { UPDATER_CONFIG } from "@/shared/constants/config";
 import { DATA_DIR } from "@/lib/dataDir";
// Source: https://github.com/decolua/9router/commit/992f4db4a0d858bcc86b4786f2abab117a6ccdf8

The patch imports an ALLOWED_MCP_COMMANDS allowlist that restricts which commands the MCP bridge is permitted to execute.

Detection Methods for CVE-2026-46339

Indicators of Compromise

  • Unauthenticated HTTP requests to /api/cli-tools/cowork-settings or /api/mcp/ from non-loopback source addresses.
  • Unexpected entries in the 9Router customPlugins configuration referencing shell binaries such as sh, bash, cmd.exe, or powershell.
  • Child processes spawned by the 9Router Node.js process that do not match the ALLOWED_MCP_COMMANDS list.
  • Outbound network connections initiated from 9Router host processes to unfamiliar destinations shortly after plugin registration.

Detection Strategies

  • Inspect web server or reverse proxy logs for POST requests to /api/cli-tools/* and /api/mcp/* originating from remote hosts prior to 0.4.37.
  • Compare running 9Router configuration against known-good plugin definitions to detect unauthorized customPlugins entries.
  • Monitor for process lineage where the 9Router process spawns interpreters or arbitrary binaries not defined in the managed plugin set.

Monitoring Recommendations

  • Enable process creation auditing on hosts running 9Router and alert on child processes of the Node.js runtime.
  • Log all HTTP requests to the 9Router API surface, including the Host and Origin headers, to identify non-loopback access attempts.
  • Alert on any modification to the 9Router persisted plugin configuration file within DATA_DIR.

How to Mitigate CVE-2026-46339

Immediate Actions Required

  • Upgrade 9Router to version 0.4.37 or later, which introduces the ALLOWED_MCP_COMMANDS allowlist and loopback-only routing.
  • Restrict network exposure of the 9Router service to localhost only and block inbound traffic to its listening port at the host firewall.
  • Audit the 9Router customPlugins configuration and remove any entries that were not deliberately provisioned.

Patch Information

The fix is available in 9Router 0.4.37. The patch, referenced in the GitHub Security Advisory GHSA-fhh6-4qxv-rpqj and applied in commit 992f4db, adds /api/cli-tools and /api/mcp to the dashboard guard, enforces a LOCAL_ONLY_PATHS list for routes that spawn child processes, and validates that both the Host and Origin headers resolve to loopback addresses.

Workarounds

  • Bind the 9Router listener to 127.0.0.1 and require access through an authenticated reverse proxy or SSH tunnel.
  • Deploy a network policy that permits access to /api/cli-tools/* and /api/mcp/* only from loopback addresses.
  • If upgrade is not immediately feasible, remove or disable the CLI tools and MCP route handlers until the patched version can be installed.
bash
# Same-host gating logic introduced in src/dashboardGuard.js (0.4.37)
const LOCAL_ONLY_PATHS = [
  "/api/cli-tools/cowork-settings",
  "/api/mcp/",
];

const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1", "::1"]);

function isLoopbackHostname(h) {
  if (!h) return false;
  const name = h.split(":")[0].replace(/^\[|\]$/g, "").toLowerCase();
  return LOOPBACK_HOSTS.has(name);
}
# Source: https://github.com/decolua/9router/commit/992f4db4a0d858bcc86b4786f2abab117a6ccdf8

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.