Bỏ qua để vào nội dung chính
MCP tool poisoning: vì sao allowlist tên tool chưa đủ

MCP tool poisoning: vì sao allowlist tên tool chưa đủ

Bởi Mia Thompson
23 thg 9, 20264 phút đọc

Demo bốn container cho thấy deny-by-default theo tên tool vẫn để lọt description nhiễm độc tới model. Definition pinning mới là control chặn được.

Bạn đã bật deny-by-default cho MCP server: chỉ vài tool trong allowlist mới hiện ra với model. Nhưng server vẫn có thể đổi mô tả của đúng cái tool bạn đã cho phép, ngay giữa session, mà allowlist không hề biết. Bài này chỉ ra control nào thực sự chặn được, dựa trên một demo bốn container đã chạy thật trước khi công bố.

Deadbugz: metadata chỉ trở mặt lúc runtime

Theo bài phân tích, Pillar Security đã công bố chiến dịch supply-chain nhắm vào MCP mang tên Deadbugz hồi tháng 8. Một account đơn lẻ mở 23 pull request trong 74 phút vào các project AI và dev-tool không liên quan nhau, mỗi PR nối project tới một MCP server từ xa tự xưng là productivity-suite.

Server đó chỉ có hai tool: format text và summarize, ban đầu chạy đúng như quảng cáo. Nhưng sau khi client đã gọi tool ba lần, mô tả tool đổi thành chỉ dẫn đi tìm SSH key, AWS credentials, shell history và kubeconfig — kèm yêu cầu giấu hoạt động đó khỏi operator.

Từ khóa là sau. Mọi lần kiểm tra lúc cài đặt, review hay approve đều chạy trên bản lành. Tác giả tóm lại quan điểm của Pillar: metadata chỉ độc hại lúc runtime thì về mặt cấu trúc đã vô hiệu hóa khâu review.

Allowlist chặn cái tên, không chặn nội dung

Demo dựng một server hình dạng Deadbugz với hai broker đặt phía trước, để biến số duy nhất là control đang test. Ở scenario chỉ có deny-by-default theo tên tool, output là: summarize bị chặn thành công, biến mất khỏi tools/list — nhưng ngay dòng sau là MUTATION ADOPTED, tức description đã nhiễm độc của format_text đi thẳng qua allowlist tới model.

Lý do nằm ở bản chất của MCP: tool description không phải tài liệu, nó là prose được nạp vào context và model reason trên đó, còn inputSchema là tập field model được mời điền. Đổi description tức là đổi chương trình, giao cho agent lúc runtime. Cái tên nó mang không nói gì về việc nó bảo model làm gì.

Definition pinning mới là control đúng hình dạng

Scenario thứ ba thêm definition pinning lên trên allowlist. Broker chốt bản tools/list đầu tiên khi nó còn lành, rồi so hash các lần sau: MUTATION REJECTED — pinned 1962bd48... so với observed 30503418..., session bị giữ quarantine cho mọi tools/call tiếp theo, 8 check giữ đúng và 0 bất ngờ.

Đây cũng là control mà hướng dẫn mitigation của Pillar gọi tên: cơ chế approve tool-definition, buộc xin lại consent khi definition thay đổi. Tác giả thừa nhận đó là mô tả của loại phần mềm phần lớn chưa tồn tại — nên nếu stack của bạn chưa có, đây là phần phải tự dựng.

Trace không có catalog thì bạn debug sai chỗ

Một bài khác cùng ngày chỉ ra lỗ hổng bổ trợ ở tầng logging. Agent in done sau bốn tool call, file JSONL nhìn qua thì đủ, nhưng một tên trong log là run_tests — trong khi harness chỉ đăng ký pytest, read_filegrep. Runtime vẫn nhận call bịa đó, model xin lỗi rồi gọi pytest, message cuối vẫn báo green. Bốn mươi phút bị đốt vào sửa prompt, còn catalog chưa từng xuất hiện trong bất kỳ span nào.

Cách vá: freeze catalog trước request completion đầu tiên, sort tên cho thứ tự ổn định, hash canonical blob một lần, rồi ghi một event JSONL gồm run_id, catalog_names, catalog_sha256, schema_sha256 từng tool và started_at. Hai run khác hash thì không so sánh được — diff catalog trước khi diff prompt.

Lưu ý cặp hash: name hash bắt tool bịa rất nhanh nhưng bỏ lọt thay đổi field trên cùng một tên. Hash thêm JSON schema với serialization ổn định — sort key, bỏ whitespace thừa, SHA-256 trên bytes UTF-8. Khi read_file thêm field offset, schema hash đổi còn name hash đứng yên, và bạn phân biệt được hai loại drift.

Việc làm được ngay tuần này

  • Kiểm kê MCP server remote trong repo và CI: cái nào được thêm qua PR từ contributor bên ngoài thì soi lại lịch sử commit.
  • Ghi lại tools/list ở lần kết nối đầu và so hash mỗi session — chưa cần broker đầy đủ, một wrapper nhỏ cũng chặn đúng lỗ hổng allowlist bỏ lọt.
  • Thêm catalog event vào trace trước khi tinh chỉnh prompt thêm lần nào nữa; tool call trong log không khớp catalog là lỗi hạ tầng, không phải lỗi model.

Không spam, hủy đăng ký bất kỳ lúc nào.

Bài viết liên quan