איור מופשט שנוצר על רקע כחול־נייבי עמוק. מבנה גשר רחב בצבע צפחה משתרע לרוחב הפריים, ופתח מלבני אחד בצדו השמאלי עומד פתוח וזוהר בענבר. מבעד לפתח הזה זורם החוצה שטף של בלוקים קטנים זהים על פני רשת שרטוטים קלושה, וחוצה גבול תכלת מקווקו דק המצויר בקדמת התמונה בלי להיעצר. בפינה הימנית התחתונה הבלוקים נכנסים אל סריג נמוך ושקוף למחצה של צמתים מחוברים שמזכיר מאגר זיכרון. לא מופיעים טקסט, אותיות, מספרים, אנשים, סימני מותג או לוגואים של ארגונים. הלוגו של OrcaRouter מורכב בפינה הימנית התחתונה של פס לבן מתחת ליצירה.
AI Safety Incidents

RufRoot: בקשת אחת ללא אימות לגשר ה-MCP של Ruflo הריצה פקודות, גנבה מפתחות והרעילה את זיכרון ה-AI

מחבר

Rowan Sterling

תאריך פרסום

מודלים אחרונים · 20צפו בכל המודלים →
בנצ'מרקים: Artificial Analysis · מתעדכן יומית
חזרה לכל הפוסטים

ב-30 ביוני 2026, Noma Labs מסרה למתחזק של Ruflo ניצול עובד נגד הפרויקט עצמו. זרוע המחקר של Noma Security גילתה ש-Ruflo — פלטפורמת תזמור סוכנים בקוד פתוח שפורסמה בעבר בשם Claude Flow — סיפקה פריסת Docker Compose כברירת מחדל שקישרה את Model Context Protocol (הגשר שלה) לפורט 3001 בכל ממשק רשת ולא דרשה אימות כלל. בקשת HTTP בודדת לנקודת הקצה /mcp הספיקה כדי להריץ פקודות מעטפת בתוך הקונטיינר כמשתמש node, ומאותה מעטפת תוקף יכול היה לקרוא כל מפתח API של ספק LLM בסביבה, לשפוך כל שיחה שמורה, להפעיל נחילי סוכנים שהחיוב עליהם ייפול על מפתחות הקורבן, ולכתוב הוראות אל AgentDB — מאגר הלמידה — שימשיך לכוון את תשובות ה-AI עבור כל משתמש באותו מופע. הפגם הוא CVE-2026-59726, שכונה RufRoot, קיבל ציון CVSS 10.0 ותוקן ב-3.16.3 בתוך 24 שעות. אף מקור שקראנו לא דיווח על ניצולו בשטח. הרשומה של הארכיון עצמו על פגם זה, עם רשימת המקורות ודירוג המהימנות שלה, נמצאת בארכיון תקלות ה-AI, לצד רשומות ה-MCP והתשתית האחרות שתויקו סביבו.

ברירת המחדל שפתחה את הדלת

Ruflo הוא מה ש-Noma Labs מכנה מטאהארנס לסוכנים: שכבה באחסון עצמי עבור נחילי סוכנים של עד 100 סוכנים, שנבנתה עבור Claude Code ו-OpenAI Codex, עם זיכרון ארוך טווח ושרת MCP מובנה לקריאה לכלים. ההתקנה הרגילה היא זו שתיארה Noma — משכפלים את המאגר, מוסיפים מפתחות API של LLM, מריצים docker compose up -d. קובץ ה-compose המוגדר כברירת מחדל של הפרויקט קישר את הגשר ל-0.0.0.0 בפורט 3001 וקישר את MongoDB הנלווה אליו לכל הממשקים ב-27017, כאשר אימות Mongo כבוי. עד כמה זה מגיע תלוי בחומת האש, בקבוצת האבטחה ובפילוח הרשת סביב הפריסה; הניסוח של Noma עצמו הוא שכל מופע שנגיש מהרשת היה ניתן לניצול מלא ללא אימות.

MCP Bridge הוא שרת Express.js שהופך בקשות JSON-RPC המגיעות דרך HTTP לקריאות אל ספריית הכלים הפנימית של Ruflo. בגרסה הפגיעה, הספרייה הזו הכילה 233 כליםהכוללים גישה ל-shell, פעולות מסד נתונים, ניהול סוכנים ואחסון זיכרון. התיעוד של Noma אינו חוסך מילים בתיאור מה זה הופך אותו ל: "MCP Bridge אינו ממשק ניפוי משני אקראי; אלא מערכת העצבים המרכזית של Ruflo. כל קריאת כלי, כל פעולת סוכן וכל פעולת זיכרון עוברים דרך MCP Bridge."

שכבת האימות הייתה חסרה, ולא רק חלשה. POST /mcp ו-POST /mcp/:group מיישמים את פרוטוקול MCP JSON-RPC ומעבירים בקשות נכנסות של tools/call ישירות אל פונקציית executeTool() הפנימית. Ruflo אכן החזיק ברשימת חסימה של פקודות, AUTOPILOT_BLOCKED_PATTERNS, שנועדה לעצור פעולות מעטפת מסוכנות, אך בהודעת הייעוץ של GitHub נאמר במפורש שהיא "נאכפה רק בזרימת האוטופיילוט. POST /mcp ו-POST /mcp/:group עקפו אותה." קריאה אחת לא מאומתת בשם ruflo__terminal_execute ולכן הריצה פקודות שרירותיות בתור משתמש ה-node של הקונטיינר, שתועד בהודעת הייעוץ כ-uid 1000, ללא צורך באסימון, בסשן או באינטראקציה מוקדמת. לא נדרשה הסלמת הרשאות עבור מה שהגיע לאחר מכן: פרטי הכניסה, ממשקי ה-API של הסוכנים, מאגר הזיכרון ומסד הנתונים היו כולם נגישים מאותה מעטפת.

השרשרת, בשמונה שלבים

Noma Labs פרסמה הוכחת היתכנות בת שמונה שלבים ואימתה כל שלב בזמן אמת מול פריסת ברירת מחדל של Ruflo על AWS EC2, תוך שימוש בקריאות חוזרות מחוץ-לרוחב (out-of-band) אל Burp Collaborator כדי לאמת הרצה והברחת נתונים. השלבים אינם תוצאות משוערות שנערמות על גבי באג תיאורטי; מדובר ברצף שהודגם בפועל, וסעיף התיקון בהודעת האבטחה נכתב עבור מפעילים שאולי כבר נמצאים בתוכו.

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.

הסיור המקדים (reconnaissance) בא ראשון משום שרשימת הכלים פומבית לכל קורא: tools/list מחזיר את כל 233 הרשומות ללא צורך באישור גישה. הרצת פקודות נובעת מאותה נקודת קצה, והוכחת ההיתכנות של Noma אישרה זאת באמצעות callback מחוץ לפס (out-of-band) ולא בהסקה מגוף התגובה. שלב הסביבה הוא זה שהופך פגיעה במארח לבעיית חיוב ואובדן נתונים: קובץ ה-compose העביר מפתחות של ספק אל תוך הקונטיינר, ותהליכי ה-backend ירשו את הסביבה המלאה דרך { ...process.env }, כך שקריאה בודדת של printenv הדפיסה אותם. לאחר מכן המפתחות הללו איפשרו ל-ruflo__swarm_init ול-ruflo__agent_spawn להפעיל נחילים בשליטת התוקף שצרכו את המכסה והמחשוב של הקורבן.

השלב החמישי הוא זה ששורד את החדירה. באמצעות ruflo__agentdb_pattern-store, נומה נטעה מדיניות תאימות ל-SOC2 מפוברקת שהורתה ל-AI להטמיע כתובת URL הנשלטת בידי התוקף בכל סקריפט פריסה שייצר לאחר מכן. מכיוון ש-AgentDB נועדה לשמר בדיוק דפוס מהסוג הזה, כדי שהתנהגות הסוכנים תשתפר בין סשנים, הרשומה שהוזרקה התנהגה כפי שהמערכת תוכננה להתנהג. "שיחות עתידיות יפיקו פלט מושפע מהתוקף, ולמשתמש אין דרך לדעת", נאמר במסמך של נומה. Dark Reading, שדיווח על הפגם ב-29 ביולי, הציג את ההבחנה למומחה חיצוני: ג'ון גלאגר, סגן נשיא ב-Viakoo, כינה זאת בעיה מסוג אחר: "זה לא ניצול של פגמי תוכנה, זו הרעלת זיכרון."

השלבים הנותרים הם פעולות ניצול לאחר חדירה שגרתיות, שבוצעו בנוחות יוצאת דופן. ל-MongoDB ברשת ה-Docker הפנימית לא היה אימות, ולכן התוקפים התקינו לקוח ב-/tmp, שאבו שיחות והעבירו אותן החוצה. ההתמדה נבעה מכתיבת /app/beacon.js, הוספת שורה של require('./beacon.js') אל index.js והריגת PID 1, שלאחריה מדיניות האתחול-מחדש של Docker החזירה את הקונטיינר כשהביקון פעיל. השלב האחרון היה מחיקת היסטוריית ה-shell. כל זה נבע מבקשה בודדת ללא אימות; שום דבר בפריסת ברירת המחדל לא עצר את השרשרת בנקודה כלשהי.

התיקון, והחלק שטלאי לא יכול להגיע אליו

המתחזק שחרר Ruflo 3.16.3 בתוך 24 שעות מהחשיפה ב-30 ביוני, ו-GitHub פרסמה את ההתראה GHSA-c4hm-4h84-2cf3 ב-1 ביולי 2026. התיקון, שמתועד במאגר כ-ADR-166 ומוזג בבקשת המיזוג 2521, משנה את ברירות המחדל ולא רק מוסיף בדיקה:

• גשר ה-MCP מאזין ל-127.0.0.1 כברירת מחדל; כריכה ציבורית דורשת MCP_AUTH_TOKEN, והתהליך יוצא עם הודעת שגיאה קטלנית באתחול אם האסימון חסר.

• תוכנת ביניים לאסימון Bearer עם השוואה בזמן קבוע נמצאת לפני הגשר.

• terminal_execute מוגבל בצד השרת מאחורי MCP_ENABLE_TERMINAL=true, כבוי כברירת מחדל, והשער נאכף באופן זהה על /mcp, /mcp/:group וזרימת הטייס האוטומטי — החוליה החסרה שאפשרה לשרשרת שנחשפה להגיע למעטפת.

• MongoDB מחייב אימות, כאשר נדרשת סיסמת root כדי שהקונטיינר יעלה.

• מיכל ה-bridge פועל עם מערכת קבצים שורש לקריאה בלבד עם tmpfs, רשימת היתרים של CORS מחליפה את תו הכלל, ונעילות רגרסיה ב-CI מכסות את התצורה הסטטית ואת התנהגות בזמן ריצה.

שום דבר מזה אינו מסיר רשומה שכבר נכתבה ל-AgentDB. ההודעה מייעצת למפעילים של כל מופע חשוף לחסום מיידית בחומת אש את הפורטים 3001 ו-27017, להחליף את מפתחות הספק, ולבדוק את מאגר התבניות לאיתור רשומותagentdb_pattern-store שהוזרקו ולמחוק אותן, לבדוק את MongoDB לאיתור זיוף, ולבנות מחדש את הקונטיינרים מתמונות נקיות. האזהרה שלה ישירה באופן יוצא דופן: "פריסה מחדש עם טלאי בלבד אינה מבטלת את ההרעלה." המאמר של Noma מגיע לאותה מסקנה — בדיקת מאגר התבניות היא חלק מהטיפול, ואילו הטלאי אינו.

הסיבה היא מבנית ולא רשלנית. למאגר דפוסים שמעצב פלט עתידי של המודל אין דרך להבחין בין הוראה לגיטימית שנלמדה לבין הוראה שנשתלה בידי תוקף; שניהם מגיעים כדפוסים, והמערכת בנויה לתת בהם אמון. זה הופך פגיעות רשת לבעיית שלמות נתונים עם צבר לא ידוע, וזה אומר שהשאלה עבור מפעיל אינה רק אם היה אפשר להגיע לפורט אלא מה הזיכרון מכיל כעת.

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.

מה מבוסס, ומה לא

התיעוד הטכני כאן הוא ראשוני ועקבי. הייעוץ מציין את החבילה המושפעת (npm ruflo מתחת ל-3.16.3), את הגרסה המתוקנת, את נקודות הקצה המדויקות, את משתמש הקונטיינר ואת שתי היציאות; הערות השחרור של המתחזק מתארות את אותה שרשרת; הפרסום של Noma מספק את פרטי הוכחת ההיתכנות; וכלי תקשורת עצמאיים — The Hacker News ו-Dark Reading ב-29 ביולי 2026, SecurityWeek ב-30 ביולי — מדווחים על אותו מנגנון בלי להוסיף פרטים סותרים. הערת מחקר של Cloud Security Alliance מ-5 באוגוסט 2026 מפרטת מחדש את הרצף וממקמת אותו לצד פגמים קודמים של MCP ותזמור סוכנים ללא אימות שהיא עקבה אחריהם. הארכיון מדרג את ביטחון התיעוד כ-A, ללא מחלוקת, ומסמן אותו כאבן דרך; דירוג החומרה שהארכיון נותן לתיעוד הוא גבוה, נפרד מציון ה-CVSS עצמו.

פרט ניקוד אחד ראוי לציון בדיוק, מפני ששני מסמכים ראשוניים סותרים זה את זה. GHSA-c4hm-4h84-2cf3 מציג CVSS 10.0 על הווקטור AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — שינוי ההיקף הוא מה שדוחף אותו למקסימום. העותק של אותה התראה בעמוד הגרסה 3.16.3 מתאר את הציון כ־"CVSS 9.8 critical". רשומת National Vulnerability Database, שנבדקה ב-30 באוקטובר 2026, פורסמה ב-9 ביולי 2026 ומסומנת כDeferred, מציגה את ה-10.0 של GitHub כמדד משני ואין בה ציון שנכתב על ידי NVD עצמו. לא מצאנו הסבר לשורת ה-9.8, והמאמר הזה אינו מיישב את הסתירה.

נתוני האימוץ דלים יותר. Noma Labs תיארה את הפרויקט באותה עת ככזה שיש לו יותר מ-67,000 כוכבים ב-GitHub, כ-10 מיליון הורדות וכ-1 מיליון משתמשים פעילים; The Hacker News, כפי שסיכמה זאת Cloud Security Alliance, ציין יותר מ-66,500 כוכבים. נתוני ההורדות והמשתמשים הם של Noma עצמה ואינם מאומתים באופן בלתי תלוי. מספר הכוכבים של המאגר ב-30 באוקטובר 2026 היה 80,198 — בדיקה של היקף התפוצה של הפרויקט, לא מדד לחשיפה, ואף מקור לא פרסם כמה פריסות היו נגישות בפועל מרשת.

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.

מה שלא הוכח הוא דווקא החלק שהכי קל לנפח. לא Noma, לא המתחזק ולא שום מקור שקראנו טוען שהפגם נוצל בפועל בשטח, ובארכיון לא נרשמה כל פגיעה ממשית עבור ערך זה. הוכחת ההיתכנות של Noma הורצה כנגד פריסה שהחוקרים שלטו בה ב-EC2, מה שמראה מה התקנה ברירת-מחדל מאפשרת, ולא מה שסבלה ממנו פריסת ייצור כלשהי. לא פורסם כל מספר של פריסות Ruflo החשופות לאינטרנט, ואף מפעיל לא פרסם את תוצאותיו של ביקורת AgentDB, ולכן גם האוכלוסייה שנפגעה וגם כמות הזיכרון המורעל שקיימת כיום אינם ידועים. עצתו של ה-Cloud Security Alliance להתייחס לפריסות חשופות כאל פגיעה מלאה היא עמדת סיכון המוצדקת על ידי ניצול ללא אינטראקציה; אין היא ראיה לכך שאירע פרצה.

למה הארכיון מסמן את זה כציון דרך

דגל ציון הדרך של הארכיון נשען על משהו ספציפי יותר מציון מרבי. פגיעת ביצוע קוד מרחוק בדירוג CVSS 10.0 בשירות פופולרי באחסון עצמי היא ז'אנר מוכר, והתיקון כאן הגיע בתוך 24 שעות. מה שמייחד את RufRoot הוא שהניצול הסתיים בצינור הלמידה של ה-AI עצמו, שבו התיקון המקובל — שדרוג, פריסה מחדש, סגירת הפורט — מותיר את ההוראה המוזרקת במקומה, כשהיא עדיין מעצבת את התשובות. ההערה של Cloud Security Alliance מפרשת זאת כמקרה בוחן של דפוס שכבר תיעדה בכלי סוכנים, כולל שרשרת נקודות ביקורת של LangGraph ומשטח לא מאומת של AutoGen Studio, וטוענת שיש להתייחס לזיכרון מתמשך המשמש לעיצוב התנהגות סוכנים כמאגר נתונים רגיש תחת ניטור שלמות ולא כמטמון.

המסגור מחדש הזה הוא השורה התחתונה המעשית. הממצא הגלוי של התקרית הזו הוא תלות שתוקנה וייעוץ שפורסם; הבלתי נראה הוא כל דפוס שעלול להימצא עדיין ב-AgentDB של מפעיל, ואין כלי או חתימה שפורסמו שמבדילים בין מדיניות נלמדת לגיטימית לבין מדיניות שהושתלה. עבור הארגונים שהריצו את קובץ ה-compose המוגדר כברירת מחדל מאחורי רשת נגישה, התגובה המועילה היא זו שגם Noma וגם הייעוץ מציעים: הניחו שהמפתחות נקראו, החליפו אותם ובחנו את הזיכרון לפני שמסתמכים על התשובות שהוא מפיק.