Hình minh họa kỹ thuật trừu tượng trên nền xanh navy đậm: một cổng vào phát sáng ở thành bên trái của một chiếc hộp trong mờ tiếp nhận một đường nét mảnh, nhạt, không mang huy hiệu và không có chìa khóa. Bên trong hộp, đường nét này gặp một chồng tấm nhỏ bo tròn và phân nhánh thành một hàng ngắn gồm những nét góc cạnh giống lệnh, di chuyển xuống một ngăn dưới chứa một cụm token hình chìa khóa phát sáng. Một cổng thứ hai đang đóng, được viền bằng màu xanh nhạt, nằm cạnh cổng vào. Không có chữ, không có người, không có logo tổ chức.
AI Safety Incidents

Một POST chưa được xác thực tới API Quản lý của Bifrost đã khởi chạy một lệnh với tư cách người dùng gateway

Tác giả

Magnus Corvin

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 14 tháng 9 năm 2026, JFrog Security Research đã công bố CVE-2026-90898, một lỗ hổng thực thi lệnh trong Bifrost — cổng AI mã nguồn mở do Maxim duy trì — và cho điểm 9,8 trên 10. Cuộc tấn công chỉ là một yêu cầu HTTP. Một yêu cầu chưa được xác thực POST /api/mcp/client đăng ký một ứng dụng khách MCP stdio, mà Bifrost đọc như tên chương trình cộng danh sách đối số và khởi chạy ngay lập tức, trước mọi bắt tay MCP, với tư cách người dùng đang chạy cổng; trên image chính thức, người dùng đó là appuser. Cổng cũng là nơi lưu khóa nhà cung cấp và khóa ảo của người vận hành, nên một tiến trình chạy ở đó có thể với tới thông tin xác thực. Điều khiến yêu cầu trở nên ẩn danh là một mặc định được phát hành sẵn: governance.auth_config.is_enabled là false, và, theo cách diễn đạt của JFrog, "tắt xác thực nghĩa là mọi người gọi đều là quản trị viên cục bộ." Không có nguồn nào được trích dẫn báo cáo rằng lỗ hổng từng bị khai thác. Các nguồn, mức độ nghiêm trọng và đánh giá độ tin cậy của chính hồ sơ nằm trong kho lưu trữ sự cố AI, cùng với các lỗ hổng cổng AI và MCP khác đã được ghi nhận trong năm qua.

Bifrost là một dịch vụ duy nhất nằm giữa một ứng dụng và các mô hình ngôn ngữ mà ứng dụng gọi tới. Kho lưu trữ của nó mô tả đây là một gateway mã nguồn mở, được cấp phép Apache-2.0, "hợp nhất quyền truy cập vào hơn 23 nhà cung cấp ... thông qua một API duy nhất tương thích OpenAI", với proxy MCP, khóa ảo, ngân sách và cân bằng tải theo từng nhà cung cấp trong số các tính năng của nó, và nó có khoảng 9.150 sao GitHub vào ngày 28 tháng 10 năm 2026. Sự kết hợp đó chính là toàn bộ lý do vì sao một shell trên máy chủ cụ thể này đáng bị chấm điểm nghiêm trọng: tiến trình định tuyến các yêu cầu cũng chính là tiến trình nắm giữ thông tin xác thực cho mọi dịch vụ thượng nguồn mà nó định tuyến tới. Hacker News, khi đưa tin về lỗ hổng vào ngày 22 tháng 9, đã nêu rõ hậu quả — vì gateway lưu khóa API cho mọi nhà cung cấp được kết nối, việc thực thi lệnh trên tiến trình gateway cho phép kẻ tấn công truy cập những thông tin xác thực đó.

Toàn bộ cuộc tấn công chỉ là một POST duy nhất

Khuyến cáo của JFrog, được công bố dưới mã tham chiếu JFSA-2026-001686326, mô tả một endpoint tồn tại để cho phép quản trị viên thêm một máy chủ MCP. Một client stdio trong đặc tả MCP không phải là URL; nó là một lệnh và các đối số của lệnh đó, mà chương trình chủ được kỳ vọng sẽ khởi chạy. Bifrost chấp nhận cấu hình đó qua API quản lý và khởi động chương trình ngay khi client được thêm. Không cần thương lượng năng lực, không kiểm tra danh tính máy chủ, không cần bắt tay thành công trước — khuyến cáo nói rõ rằng bắt tay không phải là thứ khởi động tiến trình.

Bản chứng minh khái niệm trong bản tư vấn là một phần thân JSON ngắn được gửi đến một cổng với xác thực vẫn để ở giá trị mặc định. Nó đăng ký một client có lệnh là /bin/sh và các đối số ghi ra một tệp đánh dấu, rồi đọc lại tệp đánh dấu đó. JFrog bổ sung một chi tiết vận hành quan trọng trong quá trình ứng phó sự cố: yêu cầu HTTP có thể hết thời gian chờ trong khi Bifrost đang chờ một quá trình bắt tay không bao giờ đến, và việc hết thời gian chờ trong nhật ký không có nghĩa là lệnh đã không khởi chạy. Lúc đó tiến trình đã chạy rồi.

Bản ghi CVE, do JFrog gán với tư cách là Cơ quan Đánh số CVE, ánh xạ lỗi này tới CWE-306, thiếu xác thực đối với một chức năng quan trọng, và CWE-284, kiểm soát truy cập không đúng, và nêu tên hai tệp chứa trình xử lý và middleware của nó: transports/bifrost-http/handlers/mcp.go và transports/bifrost-http/handlers/middlewares.go. Mô-đun bị ảnh hưởng là github.com/maximhq/bifrost/transports, trên Linux và macOS, đối với mọi phiên bản dưới 2.1.0.

Giá trị mặc định khiến yêu cầu trở nên ẩn danh

Không điều nào trong số đó có thể bị khai thác nếu không có điều kiện thứ hai, và điều kiện thứ hai chính là mặc định của sản phẩm. Middleware xác thực quản lý của Bifrost được kiểm soát bởi governance.auth_config.is_enabled, vốn mặc định là false. Khi tắt, middleware coi mọi bên gọi là quản trị viên cục bộ — chính phần tóm tắt của khuyến cáo nói rằng tắt xác thực nghĩa là mọi bên gọi đều là quản trị viên cục bộ — nên bước kiểm tra lẽ ra đã chặn yêu cầu không hề nằm trong luồng xử lý.

Bản sửa lỗi, pull request #6757, đã được hợp nhất vào dự án vào ngày 2 tháng 9 năm 2026, mười hai ngày trước khi CVE được công bố và sáu ngày trước bản phát hành chứa nó. Phần mô tả của nó thẳng thắn một cách bất thường về bản chất của vấn đề: pull request đóng hai primitive truy cập không xác thực trong cùng một API đăng ký, chứ không phải một. Cái đầu tiên là client stdio. Cái thứ hai là client MCP http hoặc sse trỏ đến địa chỉ loopback hoặc mạng riêng, mà pull request gọi là một primitive SSRF nhắm vào các dịch vụ nội bộ, “bao gồm endpoint metadata đám mây 169.254.169.254”. Cả hai hiện đều bị từ chối với HTTP 403 khi yêu cầu đến trình xử lý mà không có kiểm tra thông tin xác thực thực sự. Quản trị viên đã xác thực vẫn giữ cả hai khả năng, và người vận hành vẫn có thể cung cấp client stdio thông qua config.json.

Nguyên thuỷ thứ hai đó không xuất hiện trong văn bản CVE. Nó nằm trong bản vá, và đó là lý do bản sửa lỗi là một cổng chặn thay vì một việc gỡ bỏ: tính năng chưa bao giờ là lỗi. Việc coi một bên gọi chưa được xác thực là quản trị viên mới là lỗi.

Nơi API quản lý thực sự đang lắng nghe

Khả năng tiếp cận là phần của hồ sơ mà các nguồn mô tả nhất quán nhất, đồng thời cũng được đo lường ít nhất. Khuyến cáo của JFrog nêu mặc định của binary nguyên bản là localhost:8080, điều này giới hạn kẻ tấn công trong chính máy chủ. Khuyến cáo của cùng nhóm về lỗ hổng đi kèm nêu rằng image Docker chính thức thay vào đó liên kết với 0.0.0.0, và The Hacker News lặp lại điều này: image khiến API quản trị có thể được truy cập từ bên ngoài container nếu cổng được publish. Phần hướng dẫn nhanh trong README của chính Bifrost chạy lệnh "docker run -p 8080:8080 maximhq/bifrost", và tùy chọn -p của Docker publish một cổng container trên mọi giao diện của máy chủ trừ khi một địa chỉ được chỉ định. Khuyến cáo trên GitHub về lỗ hổng ghi nhận rằng đường dẫn được báo cáo đã được xác minh trên image maximhq/bifrost:latest đã publish, nơi một yêu cầu chưa xác thực đã khởi chạy /bin/sh và ghi một marker với tư cách appuser.

Điều mà không nguồn nào cung cấp là một con số. Không có số lượng các instance Bifrost hướng Internet, không có kết quả quét, không có telemetry và không có nạn nhân. Bản ghi không nêu thiệt hại thực tế nào, và sự thiếu vắng đó là một dữ kiện về cách báo cáo chứ không phải một lời trấn an — lớp lỗ hổng này chỉ nguy hiểm khi hai điều kiện trùng nhau, một listener bị lộ và một cấu hình mặc định chưa bị đụng tới, và chưa ai công bố tần suất chúng trùng nhau.

Một endpoint, hai lỗ hổng, một nguyên nhân gốc

Tám ngày trước khuyến cáo MCP, vào ngày 6 tháng 9 năm 2026, cùng nhóm nghiên cứu đã công bố CVE-2026-86242, một đường dẫn chưa xác thực thứ hai vào cùng tiến trình. Được Or Peles phát hiện và chấm 8,1 điểm, nó lợi dụng POST /api/plugins: Bifrost chấp nhận một plugin tùy chỉnh đã được bật có đường dẫn là URL HTTP; trình tải đối tượng chia sẻ coi đường dẫn có tiền tố http là một bản tải xuống, ghi nội dung vào một tệp .so tạm thời và chuyển tệp đó cho plugin.Open của Go. Nếu việc tải thành công, một hàm Init tùy chọn sẽ chạy ngay lập tức với cấu hình của kẻ tấn công, với tư cách người dùng gateway.

Biến thể bản dựng quyết định thứ mà kẻ tấn công nhận được. Trên các bản dựng liên kết động mà dự án tài liệu hóa cho các plugin Go tùy chỉnh, việc nạp được kỳ vọng sẽ thành công, điều mà khuyến nghị gọi là thực thi mã từ xa không cần xác thực. Trên image Docker liên kết tĩnh đã được phát hành, plugin.Open thất bại với "Dynamic loading not supported", nên cùng yêu cầu đó suy giảm thành giả mạo yêu cầu phía máy chủ. Một plugin có thể nạp cũng phải khớp với phiên bản Go, hệ điều hành, kiến trúc và cách liên kết của máy chủ, đây là một ràng buộc thực sự chứ không phải thủ tục hình thức. Bản sửa lỗi là transports/v2.0.0, thông qua pull request #5763, và phạm vi bị ảnh hưởng là mọi phiên bản thấp hơn nó.

Cái bẫy nằm ở thứ tự phát hành. v2.0.0 sửa đường dẫn plugin và không sửa đường dẫn MCP — The Hacker News nói rõ như vậy, và khuyến cáo MCP của JFrog xác nhận rằng v2.0.0 vẫn cho phép đăng ký stdio không xác thực. Một người vận hành đã vá kịp thời sau khuyến cáo ngày 6 tháng 9 thì, chỉ riêng ở điểm đó, vẫn bị phơi nhiễm cho đến khi transports/v2.1.0 được phát hành vào ngày 8 tháng 9. Cả hai lỗ hổng đều quy về cùng một câu trong cả hai khuyến cáo và trong chính pull request của nhà cung cấp: xác thực bị tắt là mặc định.

Những gì các nguồn chứng minh, và những gì chúng không chứng minh

Cơ chế, phạm vi phiên bản, bản vá và việc ghi công đều được thống nhất trên thông báo bảo mật, hồ sơ CVE do JFrog gán, pull request cùng ghi chú phát hành của chính dự án, và The Hacker News. Bất đồng còn lại là về mức độ nghiêm trọng, và điều đó là có thật.

9.8 là điểm của JFrog với tư cách là CNA chỉ định, và đó cũng là điểm mà NVD ghi nhận — bản ghi NVD liệt kê reefs@jfrog.com là nguồn số liệu và, tính đến ngày 28 tháng 10 năm 2026, vẫn hiển thị mục này ở trạng thái "Awaiting Analysis", nghĩa là NVD đã công bố vectơ của bên chỉ định thay vì phân tích của chính NVD về vectơ đó. Đánh giá SSVC của CISA Coordinator đính kèm cùng bản ghi đó, có dấu thời gian 14 tháng 9 năm 2026, ghi khai thác là "none", có thể tự động hóa là "yes" và tác động kỹ thuật là "total". Vào ngày 27 tháng 10 năm 2026, mô hình EPSS của FIRST ước tính xác suất bị khai thác trong 30 ngày tới là 2,3 phần trăm, nằm ở phân vị thứ 83 trong toàn bộ các CVE được chấm điểm, và cả CVE này lẫn CVE-2026-86242 đều không xuất hiện trong danh mục Lỗ hổng đã bị khai thác đã biết của CISA ngày 27 tháng 10 năm 2026.

Trái lại, Maxim phản đối mức đánh giá này. Trong một tuyên bố với The Hacker News, Akshay Deo, giám đốc công nghệ kiêm đồng sáng lập của công ty, cho biết rủi ro thực tế thấp hơn so với mức điểm nghiêm trọng gợi ý, bởi việc khai thác đòi hỏi giao diện quản trị phải truy cập được từ một mạng không đáng tin cậy và người vận hành đã để xác thực chưa được thiết lập; ông nói rằng việc triển khai mặc định và được tài liệu hóa đặt cổng vào bên trong một mạng riêng. The Hacker News đưa tin rằng Maxim coi lỗ hổng này là mức độ nghiêm trọng thấp và đang làm việc với JFrog, đơn vị đã gán CVE, để sửa đổi đánh giá. Tuyên bố đó xuất hiện ở riêng ấn phẩm đó; không tìm thấy ấn phẩm thứ hai nào trích dẫn lập trường của Maxim, và tính đến ngày 28 tháng 10 năm 2026 chưa có bản sửa đổi nào được công bố — bản ghi CVE được cập nhật lần cuối vào ngày 14 tháng 9 và mục NVD vào ngày 18 tháng 9, cả hai vẫn ở mức 9.8.

Có hai điểm thiếu sót nữa đáng được nêu rõ thay vì lấp liếm cho qua. Các thông báo bảo mật trên GitHub của dự án, được công bố ngày 23 tháng 9 năm 2026 và ghi nhận nhà nghiên cứu của JFrog là người báo cáo, vẫn giữ điểm 9.8 cho lỗ hổng MCP và 8.1 cho lỗ hổng plugin, không hề có dấu hiệu của bản chỉnh sửa mà Maxim đã mô tả. Và các phạm vi bị ảnh hưởng trong những thông báo đó được viết theo phiên bản mô-đun Go — dưới 1.5.27 và dưới 1.6.3 — chứ không phải theo các thẻ phát hành transports mà thông báo của JFrog sử dụng, nên khi đối chiếu tài liệu này với tài liệu kia, người vận hành phải dung hòa hai sơ đồ đánh số trước khi quyết định xem một bản dựng có bị ảnh hưởng hay không.

Rendered two-column card with the kicker 'BIFROST · CVE-2026-90898' and the title 'What the sources establish — and what they do not', subtitled 'Sources: JFrog JFSA-2026-001686326 (14 September 2026), the CVE record assigned by JFrog, NVD, FIRST EPSS, the CISA KEV catalogue, and the project's pull request 6757 and release tags.' The left column, headed 'ESTABLISHED' in blue, lists eight items: score 9.8 with the vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H supplied by the CNA; CWE-306 missing authentication with CWE-284 access control; unauthenticated POST /api/mcp/client starting a program as the gateway user; affected below transports 2.1.0 when management auth is disabled, the default; fixed in transports 2.1.0, PR 6757 merged 2 September, released 8 September 2026; CISA SSVC of 14 September 2026 with exploitation none, automatable yes, impact total; EPSS 2.3 percent at the 83rd percentile on 27 October 2026; and not in the CISA KEV catalogue dated 27 October 2026. The right column, headed 'NOT ESTABLISHED, OR CONTESTED' in amber, lists eight items: no exploitation reported, and the archive records real harm as false; no count of exposed or affected deployments in any cited source; severity contested, the vendor's CTO telling The Hacker News it is low; no published revision to the score as of 28 October 2026; NVD still Awaiting Analysis, so the 9.8 is the assigner's and not NVD's; affected ranges stated in two numbering schemes across the advisories; no detection or triage guidance in either advisory; and no evidence tying the flaw to any intrusion. A footer reads 'Card rendered by OrcaRouter'. The OrcaRouter logo is composited in the bottom-right corner.

Điều gì đã thay đổi và những gì người vận hành được yêu cầu làm

Trình tự thời gian chạy ngược so với thời điểm công bố, và đây là phần khó hiểu nhất của hồ sơ. Pull request #6757 được hợp nhất vào ngày 2 tháng 9 năm 2026. transports/v2.1.0, bản phát hành mà khuyến cáo nêu là bản đầu tiên chứa bản vá, được công bố vào ngày 8 tháng 9 — sáu ngày trước khi CVE-2026-90898 được công bố vào ngày 14 tháng 9. Bản vá plugin của dự án cũng đi trước khuyến cáo của chính dự án theo cách tương tự: transports/v2.0.0 được phát hành vào ngày 26 tháng 8, mười một ngày trước CVE ngày 6 tháng 9. Những người vận hành theo dõi các bản phát hành thay vì các nguồn tin đã có bản vá trước khi có cảnh báo.

Thứ mà bản nâng cấp mang lại thì hẹp và cụ thể. Trên 2.1.0 và mới hơn, một đăng ký stdio chưa xác thực sẽ trả về 403 và lệnh không khởi động; quản trị viên đã xác thực vẫn giữ được khả năng này, và việc cấp phát qua config.json vẫn hoạt động. Giải pháp tạm thời của bản khuyến cáo dành cho những ai không thể chuyển sang bản mới là đặt governance.auth_config.is_enabled thành true, dùng thông tin xác thực quản trị viên mạnh và giữ trình lắng nghe quản trị ngoài các mạng không tin cậy. Chỉ dẫn của JFrog cho các instance từng chạy lộ diện với xác thực bị tắt là không điều tra rồi hy vọng: hãy coi chúng như đã bị xâm phạm, và xoay vòng khóa ảo cùng thông tin xác thực của nhà cung cấp.

Cách suy luận từ các con số phiên bản là phần dễ bị hiểu sai nhất. v2.0.0 không khắc phục lỗ hổng này. Dòng 1.6.x tính đến 1.6.11 cũng không chứa bản sửa, và thẻ thuộc dòng 1.6 mới nhất của dự án là transports/v1.6.11, được phát hành ngày 14 tháng 8 năm 2026, không có dòng 1.7 nào trong kho tính đến ngày 28 tháng 10 năm 2026 — vì vậy không có bản phát hành đã vá nào trong dòng đó, và người vận hành 1.6.x phải chuyển sang 2.1.0 hoặc mới hơn thay vì chờ bản backport. Dòng phát hành hiện tại đã vượt xa mốc đó: transports/v2.3.2 được phát hành ngày 20 tháng 10 năm 2026.

Rendered release-timeline card with the kicker 'BIFROST · RELEASE TIMELINE', the title 'The fix shipped six days before the advisory' and the subtitle 'Dates from the project's release tags and pull request metadata, the JFrog advisories and The Hacker News. Every date below is a single day.' A horizontal timeline carries seven dated markers: 26 Aug 2026, transports 2.0.0 published; 2 Sep 2026, PR 6757 merged; 6 Sep 2026, CVE-2026-86242 published, 8.1; 8 Sep 2026, transports 2.1.0, the fix; 14 Sep 2026, CVE-2026-90898 published, 9.8; 22 Sep 2026, vendor statement reported; 23 Sep 2026, GitHub advisories published. Below it, three bars show release lines: a hatched amber bar labelled '1.6.x line' reading 'affected — no patched release in the series; newest tag 1.6.11, 14 August 2026'; a bar labelled '2.0.0' split between a pale blue segment reading 'plugin flaw fixed' and a red segment reading 'MCP flaw still open'; and a solid blue bar labelled '2.1.0 and later' reading 'MCP fix — unauthenticated stdio registration returns 403'. A foot band headed 'THE PART THAT IS EASY TO GET WRONG' notes that 2.0.0 was the patched release on 6 September and did not close the MCP path, that for the two days before 2.1.0 an operator who patched on the day of the warning was still exposed, and that the 1.6.x series has no fixed release at all. A footer reads 'Card rendered by OrcaRouter'. The OrcaRouter logo is composited in the bottom-right corner.

Có hai điều đã xảy ra sau khi công bố mà một người phòng thủ có thể tận dụng. Các thông báo bảo mật GitHub của dự án — GHSA-86gf-xh3g-rvxq cho lỗ hổng MCP ở mức nghiêm trọng và GHSA-2qp8-4xgm-fw6g cho lỗ hổng plugin ở mức cao — được đăng vào ngày 23 tháng 9 năm 2026, giúp các nguồn cấp dữ liệu về phụ thuộc và thông báo bảo mật có thêm một định danh thứ hai để đối chiếu. Và vào ngày 13 tháng 10 năm 2026, một mẫu phát hiện cho CVE-2026-90898 đã được hợp nhất vào kho lưu trữ công khai nuclei-templates, nghĩa là việc kiểm tra một nỗ lực đăng ký chưa xác thực giờ đây là thứ mà một quy trình quét có thể chạy, thay vì là thứ mà mỗi nhóm phải tự viết.

Abstract illustration on a dark navy field: a wide translucent slab representing a credential store, filled with evenly spaced glowing key-shaped tokens, stands behind a low wall. A narrow gateway aperture in the wall holds a fresh, brighter set of tokens, a blank card-shaped slip lies pushed aside on the ground in front of it, and a thin amber arc sweeps from the aperture around to the store. A second gateway aperture in the background remains closed and unlit. No text, no people, no organisation logos.

Điều còn bỏ ngỏ là mức độ nghiêm trọng, và việc này sẽ được giải quyết hay không tùy thuộc vào hai tổ chức vẫn đang trao đổi về nó. Lập trường của Maxim, theo như được báo cáo, là điểm 9.8 đánh giá quá cao một lỗ hổng chỉ có ý nghĩa khi có một listener bị lộ và một giá trị mặc định chưa được đặt — một tuyên bố về nguyên tắc có thể kiểm chứng nhưng chưa được kiểm chứng công khai, vì chưa ai công bố có bao nhiêu triển khai đáp ứng hai điều kiện đó. Lập trường của JFrog là điểm số mà họ đã gán với tư cách CNA, vẫn còn hiệu lực trong bản ghi CVE và trong NVD. Cho đến khi một trong hai bên công bố bản sửa đổi, cách đọc vận hành vẫn như nhau dù theo hướng nào: lỗ hổng là có thật và đã được xác minh từ đầu đến cuối trên container image đã công bố, bản vá đã được phát hành trước cảnh báo, dòng 1.6 hoàn toàn không có bản vá, và bất kỳ phiên bản nào chạy với xác thực bị tắt trên một listener có thể truy cập được nên được xử lý như một sự cố thông tin xác thực chứ không phải một bản vá cần lên lịch.