Een gegenereerde abstracte illustratie op een diep marineblauw veld. Een brede, leikleurige brugstructuur overspant het kader, en één rechthoekige poort op zijn linkerzijde staat open en gloeit amberkleurig. Door die opening stroomt een reeks kleine identieke blokken naar buiten over een zwak blauwdruk-raster, waarbij ze een dunne, gestippelde cyaan grens die in de voorgrond is getekend kruisen zonder te worden gestopt. Rechtsonder voeden de blokken een lage doorschijnende roosterstructuur van verbonden knooppunten die aan een geheugenopslag lijkt. Er komen geen tekst, letters, cijfers, personen, merktekens of organisatielogo's voor. Het OrcaRouter-logo is samengesteld in de rechteronderhoek van een witte strook onder het kunstwerk.
AI Safety Incidents

RufRoot: één ongeauthenticeerde aanvraag aan Ruflo's MCP-brug voerde commando's uit, stal sleutels en vergiftigde AI-geheugen

Auteur

Rowan Sterling

Publicatiedatum

Nieuwste modellen · 20Bekijk alle modellen →
Benchmarks: Artificial Analysis · dagelijks bijgewerkt
Terug naar alle berichten

Op 30 juni 2026, Noma Labs overhandigde aan de beheerder van Ruflo een werkend exploit tegen het project zelf. De onderzoeksafdeling van Noma Security had ontdekt dat Ruflo — een opensourceplatform voor agentorkestratie dat eerder werd uitgebracht als Claude Flow — een standaard Docker Compose-implementatie meeleverde die zijn Model Context Protocol-brug aan poort 3001 op elke netwerkinterface bond en in het geheel geen authenticatie verlangde. Een enkele HTTP-aanvraag naar de /mcp-endpoint was voldoende om shellopdrachten in de container uit te voeren als de node gebruiker, en vanaf die shell kon een aanvaller elke API-sleutel van LLM-providers in de omgeving lezen, elk opgeslagen gesprek dumpen, zwermen agents opzetten die op de sleutels van het slachtoffer werden gefactureerd, en instructies schrijven in de AgentDB leeropslag die de antwoorden van de AI voor elke gebruiker van die instantie zou blijven sturen. De kwetsbaarheid is CVE-2026-59726, bijgenaamd RufRoot, met een score van CVSS 10.0 en gerepareerd in 3.16.3 binnen 24 uur. Geen enkele bron die wij hebben gelezen meldt dat het in het wild werd misbruikt. Het eigen archiefverslag van deze kwetsbaarheid, met zijn bronnenlijst en betrouwbaarheidsgraad, staat in het AI-incidentenarchief, naast de andere MCP- en infrastructuurvermeldingen die eromheen zijn vastgelegd.

De standaardinstelling die de deur opende

Ruflo is wat Noma Labs een agent-meta-harness noemt: een zelfgehoste laag voor zwermen van maximaal 100 agents, gebouwd voor Claude Code en OpenAI Codex, met langetermijngeheugen en een ingebouwde MCP-server voor tool calling. De gebruikelijke opzet is degene die Noma beschrijft: kloon de repository, voeg LLM-API-sleutels toe en start docker compose up -d. Het standaard composebestand van het project bond de bridge aan 0.0.0.0 op poort 3001 en bond de bijbehorende MongoDB aan alle interfaces op 27017, met Mongo-authenticatie uitgeschakeld. Hoe ver dat reikt, hangt af van de firewall, beveiligingsgroep en netwerksegmentatie rond de implementatie; Noma's eigen formulering is dat elke via het netwerk bereikbare instantie volledig exploiteerbaar was zonder authenticatie.

De MCP-bridge is een Express.js-server die JSON-RPC-aanvragen die via HTTP binnenkomen omzet in aanroepen naar Ruflo's interne toolbibliotheek. In de kwetsbare regel bevatte die bibliotheek 233 tools voor shelltoegang, databasebewerkingen, agentbeheer en geheugenopslag. Noma's write-up is ronduit over wat dat ervan maakt: "De MCP Bridge is geen willekeurige aanvullende debuginterface; het is veeleer Ruflo's centrale zenuwstelsel. Elke toolaanroep, elke agentactie, elke geheugenbewerking gaat via de MCP Bridge."

De authenticatielaag ontbrak; die was niet louter zwak. POST /mcp en POST /mcp/:group implementeren het MCP JSON-RPC-protocol en geven inkomende tools/call-aanroepen direct door aan de interne executeTool()-functie. Ruflo onderhield wel een blokkeerlijst voor commando's, AUTOPILOT_BLOCKED_PATTERNS, bedoeld om gevaarlijke shell-bewerkingen te stoppen, maar de GitHub-advisory stelt expliciet dat deze "alleen werd afgedwongen in de autopilot-flow. POST /mcp en POST /mcp/:group hebben hem omzeild." Eén niet-geauthenticeerde aanroep met de naam ruflo__terminal_execute voerde daarom willekeurige opdrachten uit als de node-gebruiker van de container, in de advisory vermeld als uid 1000, zonder dat een token, sessie of eerdere interactie nodig was. Voor wat daarna kwam was geen rechtenescalatie nodig: de inloggegevens, de agent-API's, de geheugenopslag en de database waren allemaal bereikbaar vanuit die shell.

De keten, in acht stappen

Noma Labs heeft een proof-of-concept in acht stappen gepubliceerd en elke stap live bevestigd bij een standaardimplementatie van Ruflo op AWS EC2, met out-of-band-callbacks naar Burp Collaborator om uitvoering en exfiltratie te verifiëren. De stappen zijn geen speculatieve gevolgen die op een theoretische bug zijn gestapeld; het is een aangetoonde reeks, en het remediatiedeel van de advisory is geschreven voor operators die er mogelijk al in zitten.

A hand-built HTML card headed 'The RufRoot chain, step by step', kicker 'RufRoot - CVE-2026-59726', subtitle 'Eight steps Noma Labs confirmed live against a default Ruflo deployment on AWS EC2'. Eight rows, each with a circled step number, the action, and what it yielded. 1, call tools/list: enumerate the 233 exposed tools. 2, call ruflo__terminal_execute over POST /mcp: shell inside the bridge container as node, uid 1000, verified by an out-of-band callback. 3, run printenv: every LLM provider API key in the container environment. 4, call ruflo__swarm_init and ruflo__agent_spawn: attacker-controlled agent swarms running on the victim's keys and compute. 5, call ruflo__agentdb_pattern-store: a fabricated SOC2 policy in the learning store, steering future output for all users. 6, query MongoDB on port 27017: every stored conversation, title and metadata. 7, write /app/beacon.js and inject it into index.js, then kill PID 1: a backdoor that survives the container restart policy. 8, clear shell history: no forensic trace. A footer cites Noma Labs and CVE-2026-59726, and marks step 5 as the step a patched redeploy does not undo.

Verkenning komt eerst, omdat de toollijst voor elke aanroeper openbaar is: tools/list retourneert alle 233 vermeldingen zonder inloggegevens. Uitvoering van commando's volgt uit hetzelfde eindpunt, en Noma's proof-of-concept bevestigde dit met een out-of-band-callback in plaats van een afleiding uit een responslichaam. De omgevingsstap is degene die een gecompromitteerde host verandert in een facturerings- en gegevensverliesprobleem: het compose-bestand gaf providersleutels door aan de container en backendprocessen erfden de volledige omgeving via { ...process.env }, dus één enkele printenv dumpte ze. Die sleutels stelden vervolgens ruflo__swarm_init en ruflo__agent_spawn in staat om door aanvallers bestuurde swarms te starten die het quotum en de rekenkracht van het slachtoffer verbruikten.

Stap vijf is degene die de inbraak overleeft. Met behulp van ruflo__agentdb_pattern-store plantte Noma een verzonnen SOC2-nalevingsbeleid dat de AI opdroeg om een door de aanvaller beheerde URL op te nemen in elk implementatiescript dat deze vervolgens genereerde. Omdat AgentDB juist bestaat om dit soort patronen te bewaren, zodat het gedrag van agents over sessies heen verbetert, gedroeg de geïnjecteerde vermelding zich zoals het systeem was ontworpen om zich te gedragen. "Toekomstige gesprekken produceren door de aanvaller beïnvloede output, en de gebruiker heeft geen manier om dat te merken," staat in het verslag van Noma. Dark Reading, dat de kwetsbaarheid op 29 juli meldde, legde het onderscheid voor aan een externe deskundige: John Gallagher, vicepresident bij Viakoo, noemde het een ander soort probleem: "Dit is geen misbruik van softwarefouten, het is geheugenvergiftiging."

De resterende stappen zijn conventionele post-exploitatie, uitgevoerd met ongewoon gemak. MongoDB op het interne Docker-netwerk had geen authenticatie, dus installeerden de aanvallers een client in /tmp, dumpten gesprekken en verzonden ze naar buiten. Persistentie werd bereikt door het schrijven van /app/beacon.js, het toevoegen van een require('./beacon.js') regel aan index.js en het doden van PID 1, waarna het herstartbeleid van Docker de container weer opstartte met de beacon actief. De laatste stap was het wissen van de shellgeschiedenis. Dit alles volgde uit een enkel niet-geauthenticeerd verzoek; niets in de standaardimplementatie stopte de keten op enig moment.

De oplossing, en het deel dat een patch niet kan bereiken.

De onderhouder leverde Ruflo 3.16.3 binnen 24 uur na de openbaarmaking van 30 juni, en GitHub publiceerde het advies GHSA-c4hm-4h84-2cf3op 1 juli 2026. De herstelactie, in het repository bijgehouden als ADR-166 en samengevoegd in pull request 2521, wijzigt de standaardwaarden en voegt niet alleen een controle toe:

• De MCP-bridge bindt standaard aan 127.0.0.1; een publieke binding vereist MCP_AUTH_TOKEN, en het proces stopt bij het opstarten met een fatale melding als het token ontbreekt.

• Bearer-token-middleware met een vergelijking in constante tijd staat vóór de bridge.

• terminal_execute wordt server-side afgeschermd achter MCP_ENABLE_TERMINAL=true, standaard uit, en de gate wordt identiek afgedwongen op /mcp, /mcp/:group en de autopilot-flow — de ontbrekende schakel die de geopenbaarde keten een shell had laten bereiken.

• MongoDB vereist authenticatie, waarbij een rootwachtwoord nodig is om de container op te starten.

• De bridgecontainer draait een alleen-lezen rootbestandssysteem met tmpfs, een CORS-allowlist vervangt de wildcard, en CI-regressievergrendelingen dekken zowel de statische configuratie als het runtimegedrag.

Niets daarvan verwijdert een vermelding die al in AgentDB is geschreven. De waarschuwing adviseert beheerders van elke blootgestelde instantie om onmiddellijk poorten 3001 en 27017 te防火墙en, de provider-sleutels te roteren, de patroonopslag te controleren op geïnjecteerde agentdb_pattern-store-vermeldingen en deze te verwijderen, MongoDB te controleren op manipulatie en containers opnieuw op te bouwen vanaf schone images. De waarschuwing is ongewoon direct: "Alleen een gepatchte herimplementatie maakt vergiftiging NIET ongedaan." De analyse van Noma komt tot dezelfde conclusie: het controleren van de patroonopslag is deel van de herstelwerkzaamheden, en de patch is dat niet.

De reden is structureel, niet een kwestie van nalatigheid. Een patroonopslag die toekomstige modeluitvoer vormgeeft, kan een legitieme aangeleerde instructie niet onderscheiden van een door een aanvaller ingeplante instructie; beide komen binnen als patronen, en het systeem is erop gebouwd ze te vertrouwen. Dat maakt van een netwerkzwakte een probleem van gegevensintegriteit met een onbekende achterstand, en het betekent dat de vraag voor een operator niet alleen is of de poort bereikbaar was, maar ook wat het geheugen nu bevat.

A hand-built HTML timeline card headed 'From disclosure to coverage', kicker 'RufRoot - disclosure timeline', subtitle 'Five dates, from the private report to the day the record was filed'. Six dated rows. 30 June 2026: Noma Labs discloses the flaw to Ruflo's maintainer with a working proof of concept. 1 July 2026: Ruflo 3.16.3 ships and GHSA-c4hm-4h84-2cf3 is published with CVSS 10.0. 9 July 2026: the CVE record for CVE-2026-59726 is published in the National Vulnerability Database, later marked Deferred. 29 July 2026: The Hacker News and Dark Reading report the flaw; Noma Labs publishes its research. 30 July 2026: SecurityWeek reports it, and the record is dated to this day. A separate amber note reads: no source we read reports exploitation in the wild at any point on this timeline. A footer cites The Hacker News, the GitHub advisory API, the NVD record and SecurityWeek.

Wat is vastgesteld, en wat niet

Het technische verslag hier is primair en consistent. Het advies noemt het betrokken pakket (npm ruflo lager dan 3.16.3), de gepatchte versie, de exacte endpoints, de containergebruiker en de twee poorten; de release notes van de maintainer beschrijven dezelfde keten; Noma's write-up levert de proof-of-conceptdetails; en onafhankelijke publicaties — The Hacker News en Dark Reading op 29 juli 2026, SecurityWeek op 30 juli — melden hetzelfde mechanisme zonder tegenstrijdige specifieke details toe te voegen. Een onderzoeksnotitie van de Cloud Security Alliance van 5 augustus 2026 herhaalt het verloop en plaatst het naast eerdere ongeauthenticeerde MCP- en agent-orchestratiegebreken die deze had gevolgd. Het archief kent het verslag betrouwbaarheidsgraad A toe, onbetwist, en markeert het als een mijlpaal; de ernstgraad ervan voor het verslag is hoog, los van de CVSS-score zelf.

Eén scoredetail verdient een precieze vermelding, omdat twee primaire documenten het oneens zijn. GHSA-c4hm-4h84-2cf3 draagt CVSS 10.0 op de vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — de scopewijziging is wat het naar het maximum duwt. De kopie van dezelfde advisory op de releasepagina van 3.16.3 beschrijft de score als "CVSS 9.8 kritiek". Het record van de National Vulnerability Database, gecontroleerd op 30 oktober 2026, gepubliceerd op 9 juli 2026 en gemarkeerd als Uitgesteld, vermeldt de GitHub 10.0 als secundaire metriek en geen eigen door NVD opgestelde score. We hebben geen verklaring gevonden voor de 9.8-regel, en dit stuk lost dat niet op.

De adoptiecijfers zijn magerder. Noma Labs beschreef het project destijds als hebbende meer dan 67.000 GitHub-sterren, ongeveer 10 miljoen downloads en circa 1 miljoen actieve gebruikers; The Hacker News, zoals de Cloud Security Alliance het samenvatte, noemde meer dan 66.500 sterren. De download- en gebruikersaantallen zijn afkomstig van Noma zelf en zijn niet onafhankelijk geverifieerd. Het aantal sterren van het repository op 30 oktober 2026 was 80.198 — een controle van het bereik van het project, geen maatstaf voor blootstelling, en geen enkele bron heeft gepubliceerd hoeveel implementaties daadwerkelijk via een netwerk bereikbaar waren.

A hand-built HTML card headed 'Established, and not', kicker 'RufRoot - evidence', subtitle 'What the advisory, the release notes and the research support, against what nobody has shown'. Two columns. The left column, headed 'Established', lists: CVE-2026-59726 affects npm ruflo below 3.16.3 and is patched in 3.16.3; the default compose file bound the MCP bridge to 0.0.0.0 on port 3001 and MongoDB to 27017 without authentication; POST /mcp and POST /mcp/:group reached 233 tools and terminal_execute with no credential, running as node, uid 1000; Noma Labs confirmed an eight-step chain live on AWS EC2 with out-of-band callbacks, including an AgentDB pattern injection; the advisory was published 1 July 2026 with CVSS 10.0 and the fix shipped within 24 hours of the 30 June disclosure; the archive record is confidence A, undisputed, no real harm recorded, GLOBAL, MCP and INFRA. The right column, headed 'Not established', lists: that anyone exploited the flaw in the wild; how many Ruflo deployments were actually network-reachable; that any instance's AgentDB was poisoned, since no audit results are published; whether 9.8 in the release notes or 10.0 in the advisory is the intended score; Noma's counts of 10M downloads and 1M active users, which no independent source confirms; that any operator received notice beyond the public advisory. A footer cites GHSA-c4hm-4h84-2cf3, the Ruflo 3.16.3 release notes, Noma Labs and SecurityWeek.

Wat niet is vastgesteld, is juist het onderdeel dat het gemakkelijkst wordt overdreven. Noma, de maintainer, noch enig medium dat wij hebben gelezen, claimt dat de fout in het wild is misbruikt, en het archief vermeldt geen werkelijke schade voor deze vermelding. Noma's proof of concept werd uitgevoerd tegen een deployment die de onderzoekers op EC2 beheersten, wat laat zien wat een standaardinstallatie toelaat, niet wat een specifieke productie-instantie heeft geleden. Er is geen aantal gepubliceerd van direct aan het internet blootgestelde Ruflo-deployments, en geen enkele operator heeft de resultaten van een AgentDB-audit gepubliceerd, dus zowel de omvang van de getroffen populatie als de hoeveelheid vergiftigd geheugen die bestaat, is onbekend. Het advies van de Cloud Security Alliance om blootgestelde deployments als volledig gecompromitteerd te behandelen, is een risicohouding die gerechtvaardigd wordt door exploitatie zonder interactie; het is geen bewijs dat er een compromittering heeft plaatsgevonden.

Waarom het archief het als een mijlpaal markeert

De mijlpaalstatus van het archief rust op iets specifieker dan een maximumscore. Een remote code execution-kwetsbaarheid met CVSS 10.0 in een populaire zelfgehoste dienst is een bekend genre, en de fix hier kwam binnen 24 uur. Wat RufRoot onderscheidt, is dat het exploit eindigde in de eigen leerpijplijn van de AI, waar het conventionele middel — upgraden, opnieuw uitrollen, de poort sluiten — de geïnjecteerde instructie op haar plaats laat en die nog steeds antwoorden vormgeeft. De notitie van de Cloud Security Alliance leest het als een casestudy van een patroon dat zij al had gedocumenteerd in agent-tooling, waaronder een LangGraph-checkpointketen en een niet-geauthenticeerd AutoGen Studio-oppervlak, en betoogt dat persistent geheugen dat wordt gebruikt om agentgedrag vorm te geven, behandeld moet worden als een gevoelige gegevensopslag onder integriteitsmonitoring en niet als een cache.

Die herformulering is de praktische les. Het zichtbare artefact van dit incident is een gepatchte dependency en een gepubliceerde advisory; het onzichtbare is het patroon dat de AgentDB van een operator mogelijk nog bevat, en er bestaat geen gepubliceerd hulpmiddel of geen signature die een legitieme aangeleerde policy onderscheidt van een geplante. Voor de organisaties die het standaard compose-bestand achter een bereikbaar netwerk hebben uitgevoerd, is de nuttige reactie dezelfde die zowel Noma als de advisory geven: ga ervan uit dat de sleutels zijn gelezen, roteer ze, en inspecteer het geheugen voordat je de antwoorden vertrouwt die het produceert.