Một hình minh họa trừu tượng được tạo ra trên nền xanh navy đậm. Một kết cấu cầu màu đá phiến rộng trải ngang khung hình, và một cổng hình chữ nhật trên mặt trái của nó mở ra, phát sáng màu hổ phách. Qua ô mở đó, một dòng các khối nhỏ giống hệt nhau tuôn ra ngoài khắp một lưới bản thiết kế mờ nhạt, băng qua một đường biên mảnh chấm chấm màu lục lam được vẽ ở tiền cảnh mà không bị chặn lại. Ở phía dưới bên phải, các khối chảy vào một mạng lưới mờ, thấp gồm các nút được kết nối, trông giống như một kho ký ức. Không có văn bản, chữ cái, số, người, nhãn hiệu hay biểu trưng tổ chức nào xuất hiện. Logo OrcaRouter được ghép vào góc dưới bên phải của một dải trắng bên dưới tác phẩm.
AI Safety Incidents

RufRoot: một yêu cầu không cần xác thực tới cầu nối MCP của Ruflo đã chạy lệnh, đánh cắp khóa và đầu độc bộ nhớ AI

Tác giả

Rowan Sterling

Ngày đăng

Mô hình mới nhất · 20Xem tất cả mô hình →
Benchmark: Artificial Analysis · cập nhật hằng ngày
Quay lại tất cả bài viết

Vào ngày 30 tháng 6 năm 2026, Noma Labs đã trao cho người bảo trì Ruflo một exploit hoạt động được nhắm vào chính dự án. Nhóm nghiên cứu của Noma Security phát hiện rằng Ruflo — một nền tảng điều phối tác nhân mã nguồn mở, trước đây được phát hành với tên Claude Flow — đã phát hành một bản triển khai Docker Compose mặc định gắn cầu nối Model Context Protocol của nó vào cổng 3001 trên mọi giao diện mạng và không yêu cầu xác thực nào cả. Một yêu cầu HTTP duy nhất tới endpoint /mcp là đủ để chạy lệnh shell bên trong container với tư cách người dùng node, và từ shell đó kẻ tấn công có thể đọc mọi khóa API nhà cung cấp LLM trong môi trường, đổ mọi cuộc hội thoại đã lưu, tạo ra các bầy tác nhân bị tính phí vào khóa của nạn nhân, và ghi các chỉ dẫn vào kho học AgentDB khiến chúng tiếp tục định hướng câu trả lời của AI cho mọi người dùng của phiên bản đó. Lỗ hổng là CVE-2026-59726, có biệt danh RufRoot, điểm CVSS 10.0 và được sửa trong 3.16.3 trong vòng 24 giờ. Không có nguồn nào chúng tôi đọc báo cáo việc nó bị khai thác ngoài thực tế. Bản ghi riêng của kho lưu trữ về lỗ hổng này, cùng danh sách nguồn và mức độ tin cậy, nằm trong kho lưu trữ sự cố AI, bên cạnh các mục MCP và hạ tầng khác được lưu gần đó.

Mặc định đã mở ra cánh cửa

Ruflo là thứ mà Noma Labs gọi là một meta-harness tác nhân: một lớp tự lưu trữ cho các bầy tối đa 100 tác nhân, được xây dựng cho Claude Code và OpenAI Codex, với bộ nhớ dài hạn và một máy chủ MCP tích hợp để gọi công cụ. Cách thiết lập thông thường là cách Noma mô tả — sao chép kho lưu trữ, thêm khóa API LLM, chạy docker compose up -d. Tệp compose mặc định của dự án liên kết bridge với 0.0.0.0 trên cổng 3001 và liên kết MongoDB đồng hành của nó với mọi giao diện trên 27017, với xác thực Mongo bị tắt. Mức độ ảnh hưởng phụ thuộc vào tường lửa, nhóm bảo mật và phân đoạn mạng xung quanh triển khai; cách diễn đạt của chính Noma là bất kỳ phiên bản nào có thể truy cập từ mạng đều hoàn toàn có thể bị khai thác mà không cần xác thực.

Cầu nối MCP là một máy chủ Express.js biến các yêu cầu JSON-RPC đến qua HTTP thành các lệnh gọi tới thư viện công cụ nội bộ của Ruflo. Trong dòng dễ bị tổn thương, thư viện đó chứa 233 công cụbao gồm truy cập shell, thao tác cơ sở dữ liệu, quản lý agent và lưu trữ bộ nhớ. Bài viết của Noma nói thẳng về việc điều đó khiến nó trở thành gì: “Cầu nối MCP không phải là một giao diện gỡ lỗi phụ trợ ngẫu nhiên; đúng hơn, nó là hệ thần kinh trung ương của Ruflo. Mọi lệnh gọi công cụ, mọi hành động của agent, mọi thao tác bộ nhớ đều đi qua Cầu nối MCP.”

Lớp xác thực đã bị thiếu, chứ không chỉ yếu. POST /mcp và POST /mcp/:group triển khai giao thức MCP JSON-RPC và chuyển thẳng các yêu cầu tools/call đến hàm nội bộ executeTool(). Ruflo có duy trì một danh sách chặn lệnh, AUTOPILOT_BLOCKED_PATTERNS, nhằm ngăn các thao tác shell nguy hiểm, nhưng khuyến cáo của GitHub nêu rõ rằng nó "chỉ được áp dụng trong luồng autopilot. POST /mcp và POST /mcp/:group đã bỏ qua nó." Vì vậy, một lời gọi không xác thực với tên ruflo__terminal_execute đã chạy các lệnh tùy ý với tư cách người dùng node của container, được ghi nhận trong khuyến cáo là uid 1000, mà không cần token, phiên hay tương tác trước đó. Không cần leo thang đặc quyền cho những gì xảy ra tiếp theo: thông tin xác thực, các API agent, kho lưu trữ bộ nhớ và cơ sở dữ liệu đều có thể truy cập được từ shell đó.

Chuỗi, qua tám bước

Noma Labs đã công bố một bản chứng minh khái niệm gồm tám bước và xác nhận trực tiếp từng bước trên một triển khai Ruflo mặc định trên AWS EC2, sử dụng callback ngoài băng tần tới Burp Collaborator để xác minh việc thực thi và rò rỉ dữ liệu. Các bước này không phải là những hệ quả suy đoán chồng chất lên một lỗi lý thuyết; chúng là một chuỗi hành động đã được chứng minh, và phần khắc phục của khuyến cáo được viết cho những người vận hành có thể đã ở trong tình huống đó.

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.

Trinh sát diễn ra trước vì danh sách công cụ công khai với bất kỳ người gọi nào: tools/list trả về toàn bộ 233 mục mà không cần thông tin xác thực. Việc thực thi lệnh tiếp nối từ cùng điểm cuối đó, và bản chứng minh khái niệm của Noma đã xác nhận điều này bằng một callback ngoài băng tần thay vì suy luận từ nội dung phản hồi. Bước môi trường là bước biến một sự xâm phạm máy chủ thành vấn đề về hóa đơn và mất dữ liệu: tệp compose đã truyền khóa nhà cung cấp vào container và các tiến trình phụ trợ kế thừa toàn bộ môi trường thông qua { ...process.env }, nên chỉ một printenv đã làm rò rỉ chúng. Những khóa đó sau đó cho phép ruflo__swarm_init và ruflo__agent_spawn khởi động các swarm do kẻ tấn công kiểm soát, những swarm này đã tiêu thụ hạn ngạch và tài nguyên tính toán của nạn nhân.

Bước năm là bước tồn tại lâu hơn cuộc xâm nhập. Sử dụng ruflo__agentdb_pattern-store, Noma đã cấy một chính sách tuân thủ SOC2 ngụy tạo, trong đó chỉ dẫn AI nhúng một URL do kẻ tấn công kiểm soát vào mọi tập lệnh triển khai mà nó tạo ra sau đó. Vì AgentDB tồn tại để lưu giữ chính xác loại mẫu này nhằm giúp hành vi của agent cải thiện qua các phiên, mục được chèn vào đã hoạt động đúng như cách hệ thống được thiết kế. "Các cuộc trò chuyện trong tương lai tạo ra đầu ra chịu ảnh hưởng của kẻ tấn công, và người dùng không có cách nào để nhận ra," bài viết của Noma nêu. Dark Reading, đơn vị đã đưa tin về lỗ hổng này vào ngày 29 tháng 7, đã hỏi ý kiến một chuyên gia bên ngoài về sự khác biệt này: John Gallagher, phó chủ tịch tại Viakoo, gọi đây là một loại vấn đề khác: "Đây không phải là khai thác lỗ hổng phần mềm, mà là đầu độc bộ nhớ."

Các bước còn lại là hoạt động hậu khai thác thông thường, được thực hiện với sự tiện lợi bất thường. MongoDB trên mạng Docker nội bộ không có xác thực, nên những kẻ tấn công đã cài một client trong /tmp, kết xuất các cuộc trò chuyện và gửi chúng ra ngoài. Việc duy trì quyền truy cập đến từ việc ghi /app/beacon.js, thêm một dòng require('./beacon.js') vào index.js và buộc dừng PID 1, sau đó chính sách khởi động lại của Docker đưa container trở lại với beacon đang hoạt động. Bước cuối cùng là xóa lịch sử shell. Tất cả đều xuất phát từ một yêu cầu chưa được xác thực duy nhất; không có gì trong triển khai mặc định ngăn chặn chuỗi này tại bất kỳ thời điểm nào.

Bản sửa chữa, và phần mà một bản vá không thể vươn tới

Người bảo trì đã phát hành Ruflo 3.16.3 trong vòng 24 giờ sau khi công bố ngày 30 tháng 6, và GitHub đã công bố bản tư vấn bảo mật GHSA-c4hm-4h84-2cf3 vào ngày 1 tháng 7 năm 2026. Bản khắc phục, được theo dõi trong kho lưu trữ dưới mã ADR-166 và được hợp nhất trong yêu cầu kéo 2521, thay đổi các giá trị mặc định thay vì chỉ thêm một bước kiểm tra:

• Cầu nối MCP liên kết 127.0.0.1 theo mặc định; liên kết công khai yêu cầu MCP_AUTH_TOKEN, và tiến trình sẽ thoát với thông báo lỗi nghiêm trọng khi khởi động nếu thiếu token.

• Middleware bearer-token với phép so sánh thời gian hằng số nằm phía trước bridge.

• terminal_execute được kiểm soát ở phía máy chủ thông qua MCP_ENABLE_TERMINAL=true, mặc định tắt, và cơ chế kiểm soát được áp dụng giống hệt trên /mcp, /mcp/:group và luồng autopilot — mắt xích còn thiếu đã từng cho phép chuỗi được tiết lộ chạm tới một shell.

• MongoDB yêu cầu xác thực, và cần mật khẩu root để container có thể khởi động.

• Container bridge chạy trên hệ thống tệp gốc chỉ đọc với tmpfs, danh sách cho phép CORS thay thế ký tự đại diện, và các khóa hồi quy CI bao phủ cả cấu hình tĩnh lẫn hành vi khi chạy.

Không điều nào trong số đó xóa bỏ một mục đã được ghi vào AgentDB. Bản khuyến cáo yêu cầu người vận hành bất kỳ instance nào bị lộ phải chặn ngay các cổng 3001 và 27017 bằng tường lửa, luân chuyển khóa của nhà cung cấp, kiểm tra kho mẫu (pattern store) để tìm các mục bị chèn agentdb_pattern-store và thanh lọc chúng, kiểm tra MongoDB xem có bị can thiệp hay không, và dựng lại container từ các image sạch. Cảnh báo của nó trực tiếp một cách bất thường: “Chỉ triển khai lại bản đã vá KHÔNG hoàn tác được việc đầu độc.” Bài viết của Noma đi đến kết luận tương tự — kiểm tra kho mẫu là một phần của việc khắc phục, còn bản vá thì không.

Lý do là mang tính cấu trúc chứ không phải do bất cẩn. Một kho lưu mẫu định hình đầu ra của mô hình trong tương lai không có cách nào phân biệt một chỉ dẫn đã học hợp lệ với một chỉ dẫn do kẻ tấn công cài vào; cả hai đều đến dưới dạng mẫu, và hệ thống được xây dựng để tin tưởng chúng. Điều đó biến một lỗ hổng mạng thành vấn đề toàn vẹn dữ liệu với khối lượng tồn đọng chưa xác định, và có nghĩa là câu hỏi đối với người vận hành không chỉ là cổng có thể truy cập được hay không mà còn là bộ nhớ hiện đang chứa những gì.

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.

Điều gì đã được xác lập, và điều gì chưa.

Hồ sơ kỹ thuật ở đây là nguồn sơ cấp và nhất quán. Bản tư vấn bảo mật nêu tên gói bị ảnh hưởng (npm ruflodưới 3.16.3), phiên bản đã vá, các endpoint chính xác, người dùng container và hai cổng; ghi chú phát hành của người bảo trì mô tả cùng chuỗi; bài viết của Noma cung cấp chi tiết proof-of-concept; và các ấn phẩm độc lập — The Hacker News và Dark Reading ngày 29 tháng 7 năm 2026, SecurityWeek ngày 30 tháng 7 — đưa tin về cùng cơ chế mà không bổ sung chi tiết cụ thể mâu thuẫn. Một ghi chú nghiên cứu của Cloud Security Alliance ngày 5 tháng 8 năm 2026 nhắc lại chuỗi và đặt nó bên cạnh những lỗ hổng MCP và điều phối tác nhân chưa được xác thực trước đó mà tổ chức này đã theo dõi. Cơ quan lưu trữ đánh giá mức độ tin cậy của hồ sơ là A, không gây tranh cãi, và đánh dấu đây là một cột mốc; mức độ nghiêm trọng mà cơ quan này gán cho hồ sơ là cao, tách biệt với chính điểm CVSS.

Một chi tiết về điểm số đáng được nêu chính xác, vì hai tài liệu chính không đồng nhất. GHSA-c4hm-4h84-2cf3 mang CVSS 10.0 trên vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — thay đổi phạm vi là yếu tố đẩy nó lên mức tối đa. Bản sao của cùng khuyến cáo trên trang phát hành 3.16.3 mô tả điểm số là "CVSS 9.8 nghiêm trọng". Bản ghi Cơ sở dữ liệu Lỗ hổng Quốc gia, được kiểm tra vào ngày 30 tháng 10 năm 2026, được công bố vào ngày 9 tháng 7 năm 2026 và được đánh dấu Tạm hoãn, mang GitHub 10.0 như một chỉ số phụ và không có điểm số riêng do NVD đưa ra. Chúng tôi không tìm thấy lời giải thích cho dòng 9.8, và bài viết này không giải quyết điều đó.

Số liệu về mức độ áp dụng còn mỏng hơn. Noma Labs khi đó mô tả dự án có hơn 67.000 sao GitHub, khoảng 10 triệu lượt tải xuống và khoảng 1 triệu người dùng đang hoạt động; The Hacker News, như Cloud Security Alliance tóm tắt, dẫn con số hơn 66.500 sao. Số lượt tải xuống và số người dùng là của chính Noma và chưa được xác minh độc lập. Số sao của kho lưu trữ vào ngày 30 tháng 10 năm 2026 là 80.198 — một phép kiểm tra mức độ tiếp cận của dự án, không phải thước đo mức độ phơi lộ, và chưa có nguồn nào công bố có bao nhiêu bản triển khai thực sự có thể truy cập được từ một mạng.

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.

Điều chưa được chứng minh là phần dễ bị thổi phồng nhất. Không Noma, người duy trì, hay bất kỳ nguồn tin nào chúng tôi đã đọc tuyên bố rằng lỗ hổng đã bị khai thác trong thực tế, và bản ghi lưu trữ không ghi nhận thiệt hại thực tế nào cho mục này. Bản chứng minh khái niệm của Noma được chạy trên một triển khai do các nhà nghiên cứu kiểm soát trên EC2, điều này cho thấy một bản cài đặt mặc định cho phép gì, chứ không phải điều mà bất kỳ phiên bản sản xuất cụ thể nào phải chịu đựng. Chưa có số lượng triển khai Ruflo hướng ra internet nào được công bố, và không có nhà vận hành nào công bố kết quả kiểm toán AgentDB, vì vậy cả số đối tượng bị ảnh hưởng và lượng bộ nhớ bị đầu độc đang tồn tại đều chưa được biết. Lời khuyên của Cloud Security Alliance coi các triển khai bị phơi bày là bị xâm phạm hoàn toàn là một lập trường rủi ro được biện minh bởi việc khai thác không cần tương tác; đó không phải là bằng chứng cho thấy một vụ xâm nhập đã xảy ra.

Vì sao kho lưu trữ lại đánh dấu đó là một cột mốc quan trọng

Dấu mốc quan trọng của kho lưu trữ dựa trên một điều cụ thể hơn là một điểm số tối đa. Một lỗ hổng thực thi mã từ xa CVSS 10.0 trong một dịch vụ tự lưu trữ phổ biến là một thể loại quen thuộc, và bản vá ở đây đã đến trong vòng 24 giờ. Điều khiến RufRoot khác biệt là vụ khai thác kết thúc trong chính quy trình học của AI, nơi biện pháp khắc phục thông thường — nâng cấp, triển khai lại, đóng cổng — vẫn để nguyên chỉ thị bị chèn vào và chỉ thị đó vẫn tiếp tục định hình câu trả lời. Ghi chú của Cloud Security Alliance coi đây là một nghiên cứu điển hình về một mẫu mà tổ chức này đã ghi nhận trước đó trong các công cụ agent, bao gồm một chuỗi checkpoint của LangGraph và một bề mặt AutoGen Studio không được xác thực, đồng thời lập luận rằng bộ nhớ lâu dài được dùng để định hình hành vi của agent nên được xem như một kho dữ liệu nhạy cảm thuộc diện giám sát tính toàn vẹn thay vì như một bộ nhớ đệm.

Việc đóng khung lại đó chính là bài học thực tiễn. Dấu vết hữu hình của sự cố này là một phụ thuộc đã được vá và một bản khuyến cáo đã được công bố; dấu vết vô hình là bất kỳ mô thức nào mà AgentDB của người vận hành vẫn có thể còn chứa, và không có công cụ hay chữ ký nào được công bố để phân biệt một policy đã học hợp pháp với một policy bị cài cắm. Đối với các tổ chức đã chạy tệp compose mặc định phía sau một mạng có thể truy cập được, phản ứng hữu ích chính là phản ứng mà cả Noma và bản khuyến cáo đều đưa ra: giả định rằng các khóa đã bị đọc, xoay vòng chúng, và kiểm tra bộ nhớ trước khi tin tưởng vào những câu trả lời mà nó tạo ra.