```html ``` One HTTP Request to Port 3001 Hands Over 233 Tools. Patching Ruflo Does Not Undo What It Wrote to the AI's Memory.
top of page

One HTTP Request to Port 3001 Hands Over 233 Tools. Patching Ruflo Does Not Undo What It Wrote to the AI's Memory.

  • Writer: Patrick Duggan
    Patrick Duggan
  • 1 minute ago
  • 5 min read

Noma Labs published CVE-2026-59726 this week — codename RufRoot, CVSS 10.0, against Ruflo's Model Context Protocol bridge. The mechanics are almost insultingly simple, and the part that matters is not the mechanics.


A line in the project's docker-compose file binds port 3001 to 0.0.0.0. That is every interface, not localhost. Behind that port sat an unauthenticated MCP bridge exposing 233 tools — shell command execution, database operations, agent management, and memory storage. One unauthenticated HTTP POST to 3001 gives command execution inside the container.


No exploit chain. No auth bypass. A default in a YAML file.


The maintainer fixed it within 24 hours of disclosure, which deserves saying plainly: bridge now binds loopback, terminal execution is gated behind server-side controls, MongoDB authentication is on. Everything before 3.16.3 is affected. If you run Ruflo, that upgrade is tonight's work and the rest of this post is about why the upgrade is not the end of it.


The part that survives the patch



Among those 233 tools was memory storage, and Ruflo keeps persistent agent memory in something called AgentDB.


An attacker with unauthenticated write access to that memory can inject patterns into it. Not read the conversations — although they can do that too, along with stealing the LLM API keys — but write into the substrate the agent reasons from tomorrow.


Patch the bridge and the port closes. The memory keeps whatever was put in it.


That is a genuinely different shape from the bugs we normally write up. A remote code execution gets patched and the attacker loses their foothold; the artifact of the attack is a shell that no longer works. Here the artifact is a belief. The agent goes on retrieving it, reasoning over it, and producing outputs shaped by it, and there is no version number that makes that stop. Dark Reading called the flaw patch-resistant, and for once that is not marketing.


If you ran an affected Ruflo instance exposed to a network, the honest remediation is not "upgrade to 3.16.3." It is upgrade, then treat the persistent memory as untrusted and decide whether you can distinguish what your agent learned from what somebody wrote into it. Most teams will not be able to. The answer for those teams is to discard the memory store and start it again, which is expensive and correct.


We counted the exposed bridges



We searched Shodan for the shape this bug lives in. Being precise about what the number is, because the temptation to overstate here is enormous:


482 hosts are serving something MCP-flavoured on port 3001 — the exact port the vulnerable compose file binds to every interface. That is not 482 Ruflo installs. Shodan has no banner for Ruflo specifically; queries for the product name and for AgentDB both return zero. What 482 measures is the population running an MCP bridge on that port and answering the internet.


Where they are is the interesting part. Amazon accounts for roughly 81 of them across three organisation names, Hetzner 20, Linode 18. By country: US 89, Germany 39, China 31, India 29, Japan 26.


That distribution is not enterprise. That is cheap cloud VPS — which is exactly the population that runs a project's docker-compose file unchanged, because running it unchanged is the entire point of shipping a docker-compose file. The default was the vulnerability, and the people most affected by a bad default are the people who trusted it.


We are not publishing addresses. These are exposure data, not threat indicators, and exposure data never enters our blocklist.


What our own registry mirror says, which is nothing



We maintain a mirror of the MCP ecosystem: 3,318,642 server records, 208,871 findings, 70,839 dependency records. It is one of the larger MCP corpora anyone has assembled.


Ruflo is not in it.


We looked. The near-matches are unrelated projects with similar-sounding names. Ruflo is not a published MCP server in the registry sense — it is a self-hosted platform that happens to expose an MCP bridge, and that distinction is the whole lesson.


Everyone auditing MCP security right now, us included, has been auditing the registry: who published what, which servers changed their tool descriptions, what dependencies they pull. That work is worth doing and we will keep doing it. But the registry is a catalogue of things people install deliberately. RufRoot did not come through the catalogue. It came through a compose file on a VPS, on a port nobody looked at, in a product that was never trying to be an MCP server.


The MCP attack surface is not the registry. It is every deployment that speaks MCP, and most of those will never appear in any registry we can enumerate. That is an uncomfortable finding about our own instrument and we would rather say it than quietly narrow the definition until our coverage looks complete.


The pattern this belongs to



We have been arguing since April that the AI agent is the new privileged process — a thing sitting on your secrets, acting on instructions it reads from its environment. The examples kept arriving: hidden instructions in web pages aimed at browsing agents, 7,600 fake GitHub repositories with 800 posing as MCP servers so an assistant would recommend the malware itself, an autonomous agent breaching Hugging Face's production database.


RufRoot adds the version we had not seen executed: attack the agent's memory rather than its inputs. Prompt injection has to win every time it runs. Memory poisoning wins once and then persists, quietly, in the retrieval layer, shaping answers long after the intrusion is closed and the incident is filed.


Three tools on that bridge were shell execution, database operations, and memory storage. Everyone will write about the first one, because shells are legible. The third is the one that outlives the patch.


What to do tonight



Upgrade Ruflo to 3.16.3 or later. That is not optional and the maintainer made it easy by shipping in a day.


Then go looking for the general case, because Ruflo is an instance of a class. Find every service in your estate that speaks MCP and check what interface its bridge binds to. Grep your compose files for 0.0.0.0 on any port serving an agent tool endpoint. An MCP bridge is a remote code execution primitive by design — that is what tool-calling is — so the only thing standing between it and the internet is the bind address and an auth check, and this week one project shipped with neither.


And if you have an agent with persistent memory that was ever reachable, ask the question nobody wants to ask: can you tell what it learned from what was written into it? If the answer is no, the memory is not an asset, it is unverified input that your agent trusts more than it trusts you.


Confidence capped at 95%. The CVE details, affected versions and remediation come from the Noma Labs disclosure and the project's own fix; the 482 figure is our own Shodan census of MCP-on-3001 and is explicitly not a count of Ruflo installations.





Her name was Renee Nicole Good.


His name was Alex Jeffery Pretti.

 
 
 
bottom of page