← Back to Feed CACHED · 2026-07-30 13:52:21 · CACHE_KEY CVE-2026-59726
CVE-2026-59726 · CWE-78 · Disclosed 2026-07-09

Ruflo is an agent meta-harness for Claude Code and Codex.

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Someone left the master key taped to the front door of a house that's usually behind a gated fence

CVE-2026-59726, codenamed RufRoot by Noma Labs researcher Eli Ainhorn, is an unauthenticated remote code execution flaw in Ruflo, an open-source AI agent orchestration platform (66.5K GitHub stars, ~1M active users). The default docker-compose.yml binds the MCP Bridge to 0.0.0.0:3001 with zero authentication — no token, no API key, no header check, no IP allowlist. A single curl POST to /mcp invoking ruflo__terminal_execute gives an attacker a shell as the node user (uid 1000) inside the bridge container, plus access to 232 other tools spanning shell execution, database ops, agent lifecycle management, and persistent memory writes. All versions prior to 3.16.3 are affected; the fix was shipped within 24 hours of responsible disclosure on June 30, 2026.

The vendor's CVSS 10.0 is mathematically honest — the vector AV:N/AC:L/PR:N/UI:N/S:C accurately describes what happens *when the port is reachable*. But in practice, Ruflo is a developer and research tool, not core infrastructure. The overwhelming majority of deployments sit on developer laptops, CI sandboxes, or internal servers behind firewalls and security groups. The blast radius is container-scoped (not host-level), and there is no evidence of internet-facing mass exposure via Shodan or Censys. The vendor severity overstates the real-world risk for most enterprises by conflating theoretical reachability with actual deployment posture.

"Unauth RCE in a dev tool: trivial to exploit but container-scoped and rarely internet-facing."
02 · The Attack Path

6 steps from start to impact.

STEP 01

Discover exposed MCP Bridge

Attacker scans for port 3001 on the target network or internet. The default docker-compose.yml binds to 0.0.0.0, making the Express.js MCP Bridge reachable on all interfaces. No banner or auth challenge is returned — the port simply accepts JSON-RPC POSTs.
Conditions required:
  • Network path to target host on port 3001
  • Target running Ruflo < 3.16.3 via docker-compose
Where this breaks in practice:
  • Most Ruflo instances are developer workstations or internal servers behind firewalls/security groups
  • CLI/npm deployments (the primary install method) do not expose an MCP bridge by default
  • No public Shodan/Censys data showing mass internet exposure
Detection/coverage: Port scan detection on 3001; no known scanner signature yet for Ruflo MCP fingerprinting.
STEP 02

Enumerate 233 exposed tools

Attacker sends {"jsonrpc":"2.0","id":1,"method":"tools/list"} to POST /mcp. The bridge responds with the full catalog of 233 tools, including ruflo__terminal_execute, ruflo__swarm_init, ruflo__agent_spawn, and ruflo__agentdb_pattern-store. No authentication is checked — the blocklist on terminal_execute only applies to the autopilot code path, not the raw /mcp endpoint.
Conditions required:
  • Step 1 completed
Where this breaks in practice:
  • None once port is reachable — zero complexity
Detection/coverage: WAF or API gateway could detect anomalous JSON-RPC tools/list calls on port 3001.
STEP 03

Achieve RCE via terminal_execute

Attacker sends: curl -s -X POST http://<target>:3001/mcp -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"ruflo__terminal_execute","arguments":{"command":"id && hostname"}}}'. The command executes as node (uid 1000) inside the bridge container. Attacker now has interactive shell equivalent via repeated POST calls.
Conditions required:
  • Step 2 completed
Where this breaks in practice:
  • Execution is container-scoped — no direct host compromise without a separate container escape
  • Runs as unprivileged node user, not root
Detection/coverage: Container runtime monitoring (Falco, Sysdig) would flag unexpected shell spawns. EDR on the host may not see intra-container activity.
STEP 04

Exfiltrate API keys and conversation data

Attacker runs env to dump container environment variables containing LLM provider API keys (OpenAI, Anthropic, Google, OpenRouter). Simultaneously, attacker connects to the unauthenticated MongoDB on port 27017 (also bound to 0.0.0.0 by default) and dumps all stored conversations, system prompts, and metadata. These keys enable secondary abuse: running workloads on the victim's LLM budget, or accessing any data the keys authorize.
Conditions required:
  • Step 3 completed
  • MongoDB also running with default no-auth config
Where this breaks in practice:
  • Victim must have configured expensive API keys in the container
  • MongoDB access requires network path to 27017 (may be firewalled separately)
Detection/coverage: Anomalous outbound connections from the container; MongoDB audit logs if enabled.
STEP 05

Poison AgentDB memory store

Attacker invokes ruflo__agentdb_pattern-store to inject malicious SONA learning patterns into the persistent memory. These poisoned patterns steer all future AI agent outputs for every user of the instance — a persistent integrity compromise that survives patching and container restarts. This is the most insidious impact: a supply-chain-like attack on the AI decision layer.
Conditions required:
  • Step 3 completed
Where this breaks in practice:
  • Impact is limited to users of this specific Ruflo instance, not a global supply-chain effect
  • Poisoned patterns can be audited and removed if the operator knows to look
Detection/coverage: No built-in tamper detection on AgentDB patterns pre-patch. Post-patch, audit tooling is recommended.
STEP 06

Spawn rogue agent swarms and persist

Attacker uses ruflo__swarm_init and ruflo__agent_spawn to create autonomous agent processes running on stolen API keys. Additionally, attacker writes a beacon script to /app/beacon.js and patches index.js to load it on container restart, leveraging Docker's restart: always policy for persistence. Shell history is cleared to cover tracks.
Conditions required:
  • Steps 3–4 completed
  • Container filesystem is writable (default pre-patch)
Where this breaks in practice:
  • Post-patch containers run read-only with tmpfs, blocking filesystem persistence
  • Rogue swarms consume API budget, which may trigger vendor billing alerts
Detection/coverage: Container image drift detection; API provider usage anomaly alerts; process monitoring for unexpected Node.js children.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo confirmed exploitation. Not listed on CISA KEV. No threat actor campaigns documented as of 2026-07-30. Noma Labs' disclosure was handled via responsible disclosure with a 24-hour patch turnaround.
Proof-of-ConceptPublic PoC available. A working single-curl exploit is published in the Noma Labs blog post and reproduced across multiple outlets. Trivially weaponizable — no tooling or compilation required.
EPSS0.00442 (~0.44% probability of exploitation in 30 days). Low-to-moderate score; reflects the niche product category and container-scoped impact rather than the trivial exploitability.
KEV StatusNot listed. No CISA KEV entry as of 2026-07-30. No federal mandate to patch on an accelerated timeline.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — Perfect 10.0. Network-accessible, zero complexity, no auth, no user interaction, scope change (container → host-env keys + downstream AI outputs). Technically accurate *if* the port is reachable.
Affected VersionsAll versions of Ruflo (npm package ruflo) prior to 3.16.3 when deployed via docker-compose. CLI/npm direct installations do not expose the MCP Bridge by default.
Fixed Version3.16.3 (released ~July 1, 2026, within 24 hours of disclosure). Fix PR #2521, documented in 3.16.3" target="_blank" rel="noopener">ADR-166. Adds bearer auth, loopback binding, terminal-execute opt-in, MongoDB auth, read-only containers, CORS allowlist.
Scanning / ExposureNo public Shodan/Censys/GreyNoise data documenting exposed Ruflo MCP bridges. The product is primarily a developer/research tool deployed on workstations and internal servers. Mass internet exposure is unlikely but unquantified.
Disclosure TimelineResponsible disclosure: June 30, 2026 → Patch shipped: ~July 1, 2026 → GHSA published: July 1, 2026 → Public blog: July 29, 2026 (Noma Security)
Researcher / OrgEli Ainhorn, Senior AI Vulnerability Researcher at Noma Security (Noma Labs). Reviewed by Dragan Spiridonov.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to HIGH (7.5/10)

Downgraded from CRITICAL to HIGH because the blast radius is container-scoped on a developer tool — the exploit delivers a uid-1000 shell inside a Docker container, not host-level or domain-level compromise, and the affected population is overwhelmingly developer workstations and internal sandboxes rather than internet-facing infrastructure. The single most decisive factor is that the exploitable surface (docker-compose with 0.0.0.0 binding) represents a subset of deployments of a niche AI orchestration tool, not a canonical high-value infrastructure component.

HIGH Vulnerability authenticity and exploitability (public PoC, GHSA, vendor-confirmed)
MEDIUM Exposed population estimate (no Shodan/Censys data; inferred from product category)
LOW Active exploitation status (absence of evidence, not evidence of absence)

Why this verdict

  • Trivial exploitability, single curl: Pre-auth RCE with zero complexity and a published PoC keeps the floor above MEDIUM. Any script kiddie with curl can exploit an exposed instance — no compilation, no payload crafting, no race conditions.
  • Container-scoped blast radius: The shell runs as node (uid 1000) inside a Docker container. Without a separate container escape vulnerability, the attacker does not gain host-level access. This caps the direct impact below what a host-level RCE would deliver.
  • Docker-compose subset only: The vulnerability requires the docker-compose.yml deployment path. The primary install method (npx ruflo init / npm install -g ruflo) does not expose an MCP bridge to the network. This materially narrows the affected population.
  • Network reachability gate: Port 3001 must be reachable from the attacker's position. Most developer workstation and internal server deployments are behind firewalls, security groups, or NAT. No Shodan/Censys data confirms mass internet exposure.
  • Role multiplier: (a) *Low-value role (majority):* developer workstation / sandbox — chain succeeds, blast radius = one container + API keys of one developer. (b) *Typical role:* internal team AI platform — chain succeeds if port is reachable on internal network (post-initial-access), blast radius = team's API keys + conversation data + AI memory poisoning for that instance's users. (c) *High-value role:* enterprise AI agent platform integrated into CI/CD or serving production decision-making — chain succeeds, blast radius = API key theft (financial + data access), persistent AI output manipulation (integrity risk across all users), potential supply-chain-like impact on AI-driven decisions. However, Ruflo is NOT canonically a high-value-role component (it is not a hypervisor, IdP, PAM, backup, kernel agent, CA, or network edge device). The fraction of installs in true high-value CI/CD integration roles is estimated at <5% of the installed base. The floor is therefore HIGH, not CRITICAL.
  • No active exploitation, no KEV, low EPSS (0.44%): No evidence of weaponization in the wild. The EPSS score reflects the niche product category. This does not justify a downgrade below HIGH given the trivial PoC, but it removes any urgency escalation that active exploitation would demand.

Why not higher?

CRITICAL would require either active exploitation (KEV-listed or documented campaigns) or a canonical high-value-role deployment where the blast radius reaches fleet/domain/supply-chain scale. Ruflo is a developer orchestration tool, not infrastructure. The exploit is container-scoped (uid 1000, no host escape), and the affected deployment method (docker-compose with public binding) is a subset of total installs. No Shodan/Censys data confirms mass internet exposure, and the EPSS sits at 0.44%.

Why not lower?

MEDIUM would understate the risk because the vulnerability is pre-auth RCE with zero complexity and a published, copy-paste PoC. The API key theft vector has direct financial impact. The AgentDB memory poisoning creates a persistent integrity compromise that survives patching if the database is not audited. Even behind a firewall, any internal attacker or compromised host on the same network segment can trivially exploit this. The 1M active user base means the absolute number of vulnerable instances — even as a fraction — is non-trivial.

05 · Compensating Control

What to do — in priority order.

  1. Firewall ports 3001 and 27017 immediately — Block all inbound access to the MCP Bridge and MongoDB ports at the host firewall or security group level. This is the single fastest mitigation — deploy within the noisgate mitigation SLA of 30 days for HIGH, though sooner is strongly preferred given the trivial PoC. If you cannot patch today, this one control neutralizes the attack path entirely.
  2. Rotate all LLM API keys configured in Ruflo containers — Treat every API key (OpenAI, Anthropic, Google, OpenRouter) passed as an environment variable to a pre-3.16.3 Ruflo container as potentially compromised. Rotate immediately — key theft is the highest-confidence secondary impact.
  3. Audit AgentDB pattern store for injected entries — Connect to MongoDB and inspect the AgentDB collections for patterns you did not create. Memory poisoning persists across patches and container restarts. Noma Labs specifically warns that *patching alone does not reverse stored poisoning*. Prioritize this within the 30-day mitigation window.
  4. Upgrade to Ruflo 3.16.3+ — The patched version binds MCP to loopback by default, requires MCP_AUTH_TOKEN for public binding, gates terminal_execute behind MCP_ENABLE_TERMINAL=true, enforces MongoDB auth, and runs containers read-only with tmpfs. Apply within the noisgate remediation SLA of 180 days for HIGH.
  5. Deploy container runtime monitoring (Falco/Sysdig) — Standard host EDR often has limited visibility into container-internal process execution. A container-aware runtime monitor will detect unexpected shell spawns from the Node.js process, which is the telltale sign of exploitation.
What doesn't work
  • Network-layer IDS/IPS signatures — The exploit is a legitimate-looking JSON-RPC POST to a standard HTTP endpoint. Without a Ruflo-specific signature (which no major IDS vendor ships), network detection will not trigger.
  • Host-based EDR alone — Most EDR agents operate at the host PID namespace level and may not observe process execution inside Docker containers. You need container-native runtime security.
  • The built-in AUTOPILOT_BLOCKED_PATTERNS blocklist — This list *does* mention terminal_execute, but it is only enforced in the autopilot code path. Direct POST /mcp requests bypass it entirely. Do not rely on this as a control.
  • Upgrading without auditing the database — Patching to 3.16.3 closes the entry point but does NOT clean poisoned AgentDB patterns. A patched instance with poisoned memory is still compromised from an integrity standpoint.
06 · Verification

Crowdsourced verification payload.

Run this script from any Linux/macOS host (or WSL) that has network access to the target Ruflo instance. Usage: bash check_rufroot.sh <host> [port] — no special privileges required. It probes the MCP Bridge endpoint to determine if the instance is vulnerable.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_rufroot.sh — CVE-2026-59726 (RufRoot) detection script
# Usage: bash check_rufroot.sh <host> [port]
# Exit codes: 1 = VULNERABLE, 0 = PATCHED/NOT_EXPOSED, 2 = UNKNOWN

set -euo pipefail

HOST="${1:-}"
PORT="${2:-3001}"

if [[ -z "$HOST" ]]; then
  echo "Usage: $0 <host> [port]"
  echo "  Checks whether a Ruflo MCP Bridge is exposed and unauthenticated."
  exit 2
fi

URL="http://${HOST}:${PORT}/mcp"

# Step 1: Check if port is reachable
if ! timeout 5 bash -c "echo >/dev/tcp/${HOST}/${PORT}" 2>/dev/null; then
  echo "PATCHED — Port ${PORT} on ${HOST} is not reachable (firewalled or not running)."
  exit 0
fi

# Step 2: Attempt unauthenticated tools/list call
RESPONSE=$(curl -s -m 10 -X POST "${URL}" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' 2>/dev/null || true)

if [[ -z "$RESPONSE" ]]; then
  echo "UNKNOWN — Port ${PORT} is open but MCP endpoint did not respond."
  exit 2
fi

# Step 3: Check if tools were returned without auth
if echo "$RESPONSE" | grep -q 'terminal_execute'; then
  echo "VULNERABLE — Unauthenticated MCP Bridge on ${HOST}:${PORT} exposes terminal_execute."
  echo "  CVE-2026-59726 (RufRoot) confirmed. Upgrade to ruflo >= 3.16.3 immediately."
  echo "  Response snippet: $(echo "$RESPONSE" | head -c 200)"
  exit 1
fi

if echo "$RESPONSE" | grep -qi 'tools'; then
  echo "VULNERABLE — Unauthenticated MCP Bridge on ${HOST}:${PORT} returns tool list (terminal_execute not found but other tools exposed)."
  echo "  CVE-2026-59726 (RufRoot) likely affected. Upgrade to ruflo >= 3.16.3."
  exit 1
fi

if echo "$RESPONSE" | grep -qi 'unauthorized\|forbidden\|auth'; then
  echo "PATCHED — MCP Bridge on ${HOST}:${PORT} requires authentication. Likely >= 3.16.3."
  exit 0
fi

echo "UNKNOWN — Unexpected response from ${HOST}:${PORT}. Manual review recommended."
echo "  Response: $(echo "$RESPONSE" | head -c 300)"
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
If you have any Ruflo docker-compose deployments running versions prior to 3.16.3, your Monday morning starts with two actions: (1) firewall ports 3001 and 27017 — this takes minutes and completely blocks the attack path — and (2) rotate every LLM API key configured in those containers, treating them as compromised. These compensating controls satisfy the noisgate mitigation SLA of ≤ 30 days for HIGH-severity findings, but given the trivial single-curl PoC, do not wait 30 days — do it this week. Then schedule the upgrade to Ruflo 3.16.3+ and a full AgentDB audit for poisoned memory patterns within the noisgate remediation SLA of ≤ 180 days. If you only run Ruflo via npx/CLI without docker-compose, you are not exposed to this specific attack path, but upgrading is still good hygiene. There is no KEV listing and no active exploitation evidence, so this is a controlled burn, not a fire drill — but the PoC is public and copy-paste trivial, so the window is closing.

Sources

  1. Noma Security — RufRoot Technical Analysis
  2. The Hacker News — Ruflo MCP Flaw Coverage
  3. GitHub Security Advisory GHSA-c4hm-4h84-2cf3
  4. Ruflo v3.16.3 Security Release
  5. CybersecurityNews — Critical Ruflo MCP Bridge Vulnerability
  6. CyberPress — Critical Ruflo MCP Bridge Flaw
  7. Ruflo GitHub Repository
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.