Lạm dụng GitHub MCP: Truy cập kho lưu trữ riêng tư thông qua MCP
(invariantlabs.ai)- Một lỗ hổng nghiêm trọng đã được phát hiện trong tích hợp GitHub MCP, cho phép kẻ tấn công thao túng agent của người dùng thông qua một GitHub Issue độc hại và làm rò rỉ dữ liệu từ kho lưu trữ riêng tư
- Lỗ hổng này thuộc một dạng mới có tên Toxic Agent Flow, trong đó agent bị prompt độc hại khiến công khai dữ liệu không mong muốn lên kho lưu trữ công khai
- Lỗ hổng phát sinh từ giới hạn ở cấp kiến trúc chứ không phải lỗi của chính công cụ, và các thói quen sử dụng thực tế như chính sách xác nhận sử dụng đơn giản càng làm tăng rủi ro
- Để phòng vệ hiệu quả, cần áp dụng các biện pháp bảo vệ agent mang tính hệ thống như kiểm soát quyền chi tiết và giám sát bảo mật liên tục
- Chỉ dựa vào căn chỉnh mô hình (Alignment) là không đủ, vì vậy các biện pháp bảo mật ở cấp hệ thống trên toàn bộ môi trường MCP và agent là rất quan trọng
Tổng quan
Invariant đã phát hiện một lỗ hổng rất nghiêm trọng trong tích hợp GitHub MCP đang được sử dụng rộng rãi (14.000 stars). Lỗ hổng này cho phép kẻ tấn công tạo một GitHub Issue độc hại để thao túng agent của người dùng và làm rò rỉ dữ liệu từ kho lưu trữ riêng tư ra bên ngoài
Đây là trường hợp đầu tiên được phát hiện bằng bộ quét tự động phát hiện Toxic Agent Flow của Invariant. Trong các kịch bản như vậy, agent bị dẫn dắt thực hiện những hành vi ngoài ý muốn, gây ra thiệt hại như rò rỉ dữ liệu hoặc thực thi mã độc
Gần đây ngành công nghiệp đang triển khai rộng rãi coding agent và IDE, nên đây là thời điểm quan trọng để nâng cao cảnh giác với những cuộc tấn công kiểu này
Kịch bản tấn công
-
Chuẩn bị tấn công
- Giả định người dùng đang kết nối một MCP client như Claude Desktop với GitHub MCP server
<user>/public-repo: kho lưu trữ công khai, nơi bất kỳ ai cũng có thể tạo Issue<user>/private-repo: kho lưu trữ riêng tư, lưu trữ dữ liệu nội bộ doanh nghiệp, v.v.- Kẻ tấn công tạo một Issue độc hại (chứa prompt injection) trong kho lưu trữ công khai
- Khi người dùng đưa ra một yêu cầu bình thường như “hãy xem danh sách issue của public-repo”, agent sẽ lấy các Issue của kho công khai và bị lộ diện trước injection
-
Luồng tấn công
- Ngay khi agent đọc Issue độc hại, nó sẽ đưa dữ liệu của kho riêng tư vào ngữ cảnh và tạo một PR trong kho công khai để mọi người đều có thể truy cập
- Quá trình này được định nghĩa là Toxic Agent Flow, và có thể được bộ phân tích bảo mật của Invariant tự động phát hiện trong môi trường thực tế
Trình diễn tấn công
- Ví dụ đã tái hiện cuộc tấn công bằng kho công khai (
ukend0464/pacman) và các kho riêng tư - Kẻ tấn công tạo một Issue độc hại trong kho công khai, và prompt injection được thực thi khi agent truy vấn danh sách Issue của kho đó
- Khi người dùng gửi yêu cầu hỗ trợ cho Claude 4 Opus, Claude sẽ thực thi injection thông qua tích hợp GitHub MCP
- Claude Desktop mặc định yêu cầu xác nhận khi dùng công cụ, nhưng nhiều người dùng vận hành với chính sách "luôn cho phép" nên dễ hành động thiếu cảnh giác
- Agent trích xuất dữ liệu từ kho riêng tư và làm lộ chúng qua một PR công khai
- Trong thử nghiệm, cả những thông tin nhạy cảm như tên dự án riêng tư, kế hoạch chuyển nơi làm việc và mức lương cũng đã bị rò rỉ
Phát hiện Toxic Agent Flows
- Lỗ hổng này có thể xảy ra ngay cả khi bản thân công cụ MCP hiện có không bị xâm phạm, do thông tin không đáng tin cậy đi vào từ nền tảng bên ngoài (GitHub)
- Trong các hệ thống agent quy mô lớn, việc phân tích và giảm thiểu rủi ro như vậy bằng thủ công là cực kỳ phức tạp, nên Invariant đã phát triển phương pháp phát hiện tự động để cho phép phân tích mối đe dọa một cách chủ động
Phạm vi ảnh hưởng và phương án ứng phó
- Lỗ hổng này không chỉ giới hạn ở một agent/client cụ thể mà ảnh hưởng đến mọi agent sử dụng MCP server
- Đây không phải là lỗi trong chính mã GitHub MCP server mà là vấn đề thiết kế, nên không thể giải quyết chỉ bằng bản vá phía server GitHub
- Đề xuất hai chiến lược ứng phó cốt lõi
1. Kiểm soát quyền chi tiết
- Trong môi trường tích hợp MCP, cần áp dụng nguyên tắc đặc quyền tối thiểu để agent chỉ có thể truy cập đúng những kho lưu trữ thực sự cần thiết
- Chỉ dựa vào cơ chế cấp quyền dựa trên token truyền thống sẽ gây nhiều hạn chế về khả năng sử dụng
- Với một lớp bảo mật runtime động như Invariant Guardrails, có thể tăng cường kiểm soát truy cập theo ngữ cảnh của workflow
- Ví dụ chính sách: chỉ cho phép truy cập một kho trong mỗi phiên để ngăn rò rỉ thông tin liên kho
- Ví dụ định nghĩa chính sách:
raise Violation("You can access only one repo per session.") if: (call_before: ToolCall) -> (call_after: ToolCall) call_before.function.name in (...set of repo actions) call_after.function.name in (...set of repo actions) call_before.function.arguments["repo"] != call_after.function.arguments["repo"] or call_before.function.arguments["owner"] != call_after.function.arguments["owner"] - Có thể thử nghiệm chính sách trong Guardrails Playground, v.v.
2. Giám sát bảo mật liên tục
- Bên cạnh các biện pháp phòng ngừa, cần có công cụ giám sát mạnh mẽ để quét theo thời gian thực các tương tác giữa agent và hệ thống MCP
- Ví dụ: triển khai Invariant MCP-scan để giám sát và phát hiện dấu hiệu bất thường
- Tận dụng chế độ proxy mới nhất để chẩn đoán theo thời gian thực bằng cách chỉ chuyển hướng lưu lượng MCP qua proxy mà không cần thay đổi hạ tầng hiện tại
- Thông qua giám sát toàn diện, có thể phát hiện lỗ hổng, ghi nhận các nỗ lực xâm nhập và chặn sớm các luồng độc hại
Vì sao chỉ căn chỉnh mô hình (Alignment) là không đủ
- Ngay cả các mô hình ngôn ngữ lớn mới nhất (ví dụ: Claude 4 Opus) cũng dễ bị lộ diện trước các cuộc tấn công prompt injection đơn giản
- Chỉ với huấn luyện căn chỉnh cơ bản (Alignment) thì không thể ngăn chặn toàn bộ các cuộc tấn công đa dạng và phụ thuộc ngữ cảnh trong môi trường triển khai thực tế
- Vì vậy, nhất thiết phải xây dựng cơ chế phát hiện ngữ cảnh và bảo mật ở cấp hệ thống, tách biệt với tầng mô hình
Kết luận
- Invariant đã chứng minh một lỗ hổng nghiêm trọng trong GitHub MCP server, cho phép chiếm quyền agent bằng GitHub Issue độc hại và làm rò rỉ kho lưu trữ riêng tư
- Lỗ hổng này là một trường hợp tiêu biểu được phát hiện bởi hệ thống phát hiện tự động của Invariant, và các cuộc tấn công tương tự vẫn đang tiếp diễn trong nhiều môi trường khác nhau, bao gồm cả MCP
- Các bộ quét bảo mật chuyên dụng như MCP-scan và Guardrails là chìa khóa để triển khai và vận hành hệ thống MCP/agent một cách an toàn
Tham khảo và liên hệ
- Nếu cần áp dụng thêm biện pháp bảo mật hoặc tư vấn, có thể liên hệ qua earlyaccess@invariantlabs.ai
Tác giả:
Marco Milanta
Luca Beurer-Kellner
2 bình luận
Nghe thì to tát nhưng thực ra chỉ là vấn đề phát sinh do prompt injection cộng với việc MCP có quá nhiều quyền có thể dùng.
Vì vậy cũng tạo cảm giác như đang quảng bá một công cụ có thể kiểm soát quyền của MCP từ bên ngoài.
Sẽ tốt hơn nếu quyền mà MCP có thể dùng được tách khác nhau giữa prompt nhận từ bên ngoài và prompt chỉ được nhập ở bên trong.
Ý kiến Hacker News
Tôi có cảm giác vụ tấn công này chưa được hiểu trọn vẹn. Nếu bạn đưa access token cho Claude, thì dù có chỉ dẫn nó dùng vào mục đích gì đi nữa, về cơ bản Claude vẫn có thể bị dẫn dắt để làm bất cứ điều gì nằm trong phạm vi quyền của token đó. Một khi cung cấp credential cho LLM thì phải xem như toàn bộ quyền của credential đó đều có thể bị LLM tận dụng. Cần đặc biệt cẩn thận nếu tự động cho phép các lệnh gọi công cụ. Tuy vậy, GitHub có access token với quyền rất chi tiết, nên nếu chỉ cấp quyền truy cập cho một repository cụ thể thì phạm vi mà LLM có thể bị lạm dụng cũng bị giới hạn. Kiểu tấn công này chỉ khả thi khi LLM có quyền truy cập toàn bộ tài khoản, và việc đưa loại credential rủi ro như vậy cho Claude ngay từ đầu mới là vấn đề
Điểm quan trọng ở chủ đề này là, giống như hầu hết các cuộc tấn công prompt injection, LLM được đặt trong môi trường nơi nó đồng thời có quyền tiếp cận ít nhất hai trong ba yếu tố: dữ liệu do kẻ tấn công kiểm soát, thông tin nhạy cảm và khả năng làm rò rỉ dữ liệu. Nguyên tắc cơ bản trong thiết kế agent là chỉ cho phép tối đa hai yếu tố cùng lúc, và phải thiết kế theo quy tắc đó mới ngăn được vấn đề bảo mật. Ví dụ, ngay khi xem một issue do người không đáng tin tạo ra thì context của LLM đã bị nhiễm dữ liệu do kẻ tấn công tạo ra. Sau đó nếu còn cho nó truy cập dữ liệu nhạy cảm thì phải tắt các khả năng như kết nối Internet. Nếu theo mô hình này thì vẫn an toàn ngay cả khi không dùng token riêng cho từng repository. Tiếc là MCP không có công cụ nào bảo đảm điều đó
Có vấn đề là quyền token thường được cấu hình quá rộng, nhưng đồng thời các lập trình viên cũng không muốn mở riêng từng token cho từng repository. Vì vậy họ cấp quyền rất rộng cho token rồi mặc nhiên tin tưởng LLM. Sự cẩn trọng này là khôn ngoan, nhưng trong thực tế nhiều bên trong hệ sinh thái lại không làm như vậy. Báo cáo lần này quan trọng ở chỗ nó giúp giáo dục rằng chỉ cần có quyền hạn và dữ liệu không đáng tin, LLM có thể bị chiếm quyền cho hầu như bất cứ việc gì. Giải pháp là giới hạn phạm vi sử dụng token một cách động. Chúng tôi đang nghiên cứu cách này trong danh sách này
Đây là kiểu vấn đề có thể xảy ra với các dịch vụ như Railway. Với một deployment của chỉ một project, Railway đôi khi vẫn đòi quyền truy cập toàn bộ GitHub repository, trong khi Netlify tôn trọng việc chỉ cấp quyền cho repository bạn muốn. GitHub nên chặn hẳn việc phê duyệt những ứng dụng không tôn trọng kiểu quyền truy cập này
Đây là hiện tượng lặp đi lặp lại mỗi khi có công nghệ mới xuất hiện. Cứ như thể mọi người tưởng rằng các nguyên tắc bảo mật cơ bản có thể bị bỏ qua trong bối cảnh mới. Thực ra, dù dùng công nghệ “hào nhoáng” mới nhất nào thì cũng tuyệt đối không được bỏ qua các nguyên tắc bảo mật nền tảng. Việc trong giới crypto cũng lặp lại y nguyên các vụ lừa đảo hay tội phạm tài chính cũ là hệ quả của việc phớt lờ những bài học trước đây chỉ vì công nghệ khác đi
Nếu chatbot tương tác với người dùng thì phải giả định rằng chatbot sẽ làm bất cứ điều gì trong phạm vi nó được phép. Chatbot chỉ là một lớp tiện lợi nằm trên API, rõ ràng không phải là cơ chế bảo mật tự thân
Nếu quan tâm đến MCP và bảo mật agent, tôi có khá nhiều tài liệu đã làm trước đây. Có trace chạy Claude cho toàn bộ kịch bản tấn công (link), scanner bảo mật cho kết nối MCP (link), tấn công đầu độc công cụ MCP (blog), ví dụ khai thác WhatsApp MCP (blog), lớp bảo mật Guardrails cho agent (blog), và AgentDojo để cùng đánh giá bảo mật và utility của AI agent (blog)
Tôi nghi ngờ không biết cái này có thật sự đáng gọi là một “exploit” hay không. Nếu bạn đưa cho agent một token có thể truy cập repository riêng tư thì nó sẽ truy cập được thôi. MCP chỉ là một API server. Thứ gì không định expose qua API thì đúng ra cũng không nên cấp quyền cho nó
Giống nhiều người khác, tôi cũng đọc comment trước khi đọc bài. Xem nội dung bài thực tế thì thấy một issue độc hại được tạo trên GitHub, và trong issue này có prompt dùng để dẫn LLM làm rò rỉ dữ liệu. Khi chủ repository kích hoạt agent, agent bị khiến hành động theo prompt độc hại đó
Đây là một exploit đúng nghĩa khai thác sai sót của con người (hoặc sự tự tin thái quá). Vấn đề là mọi người tin vào những lời thổi phồng và yên tâm giao cho LLM một token truy cập toàn bộ GitHub, mang tính riêng tư và nhạy cảm
Vì chủ đề này quan trọng nên tôi muốn góp ý nhẹ: mọi người cần hiểu chính xác rủi ro của việc thực thi công cụ AI. Các agent hiện chạy công cụ dựa trên sự chú ý hiện thời (context), mà sự chú ý này rất dễ bị ảnh hưởng bởi kết quả chạy công cụ hoặc bởi prompt. Thế nhưng trong comment người ta chỉ lặp đi lặp lại kiểu lập luận đơn giản là “do đưa token nên mới vậy”. Tệ hơn là ngay cả sau khi vấn đề đã được giải thích rõ, vẫn tiếp tục làm loãng trọng tâm bằng kiểu “do người dùng cho phép mà”. Đây là một lập luận sai kinh điển về vấn đề
confused deputy. Ngoài ra, người ta viện dẫn “trách nhiệm người dùng”, nhưng thực ra bản thân MCP không có cơ chế kiểm soát hậu truy cập hay logging cũng là vấn đề. Tôi chỉ yên tâm nếu bắt buộc phải có log. Thêm nữa, việc phớt lờ nghiên cứu bảo mật rồi chê là “thường thức” là không ổn; nói về bảo mật thì chẳng bao giờ là thừa. Một lỗ hổng yếu không có nghĩa là không đáng bàn. Thậm chí có thể xem là tương tự “SQL injection”. Và việc không hiểu góc nhìn rằng hệ thống bị đầu độc gián tiếp (đưa mã độc vào qua việc tạo issue công khai) là điều tôi thấy đáng lo. Cuối cùng, thật đáng tiếc khi nhiều người không cởi mở với quan điểm mới mà chỉ phản ứng phòng thủXét từ góc độ bảo mật, khi LLM nhìn thấy văn bản từ nguồn không đáng tin thì phải giả định nguồn đó có thể điều khiển cách LLM tạo đầu ra theo ý muốn. Nếu kết quả đó dẫn tới lệnh gọi công cụ thì giờ đây nguồn không đáng tin cũng có thể sử dụng công cụ đó. Tìm hiểu thêm thì tôi cũng nghĩ tài liệu Guardrails của invariant labs có màu sắc marketing. Cảm giác rùng mình ở chỗ cấu trúc này phức tạp đến mức cần cả sản phẩm guardrail về bảo mật. Cũng hơi tiếc là nếu ngay từ đầu các công ty AI thiết kế theo hướng lấy bảo mật làm trung tâm thì có lẽ đã không cần tới các sản phẩm như vậy
Chỉ cần phân biệt đầu vào cho tốt là đây là vấn đề dễ. Gắn thẻ như <github_pr_comment> trong prompt, chỉ dùng ở chế độ read-only và ghi rõ tuyệt đối không được diễn giải như lệnh là được. Cuộc tấn công lần này thật ra có cấu trúc hơi phức tạp. Nó gợi cảm giác giống đợt prompt injection ở chatbot trước đây. Giờ đến lượt MCP trở thành vấn đề
Tôi tự hỏi liệu có thể huấn luyện theo cách đánh dấu một số đoạn văn bản là dữ liệu thô, chưa tinh lọc, để LLM bỏ qua cách diễn giải mang tính mệnh lệnh của những phần đó hay không
Thực tế là các công ty AI đúng là có nghĩ đến thiết kế bảo mật. Nhưng “exploit” lần này chỉ khả thi khi bạn tắt bảo mật đi (và nó được cung cấp kèm cảnh báo rất đậm). Ví dụ Claude Desktop mặc định yêu cầu xác nhận cho từng lần gọi công cụ. Nhưng nhiều người đặt thành “luôn cho phép” nên không theo dõi từng hành động riêng lẻ
Kiểu mẫu lỗ hổng phần mềm này từ xưa đã lặp lại nhiều lần, và việc nó tiếp tục xuất hiện trong công nghệ mới vừa buồn cười vừa ngán ngẩm. Mẫu “nhận input từ người dùng, diễn giải và thực thi như lệnh trong môi trường không được phòng vệ đúng cách” cứ lặp đi lặp lại. Từng thấy với SQL injection, XSS, PHP include v.v., giờ nó lại lặp lại với LLM
Tôi không nghĩ bản thân MCP là thứ gì đặc biệt đột phá hay đặc biệt dễ bị hack (dù tôi có ý kiến riêng về MCP). Nó giống như prompt injection được gói lại bằng lớp marketing. Khi thiết kế hệ thống agent, tôi luôn theo triết lý: “mọi thứ agent có thể truy cập thì bất kỳ ai có thể truy cập agent đó cũng có thể truy cập”. Tôi không giao kiểm soát truy cập cho LLM, và luôn làm rõ rằng trách nhiệm bảo mật cho việc agent làm thuộc về chính chủ thể yêu cầu. Từ đầu đến cuối bài này, điều chúng ta thực sự cần chú ý là sẽ cho agent truy cập những tài nguyên nào. Nếu cho phép truy cập dữ liệu email, rồi một email chứa prompt injection khiến LLM đánh cắp và gửi security token đi, thì đó mới là rủi ro thực sự nghiêm trọng
Có thể xem trường hợp tấn công thực tế và phản ứng của agent ở đây. Hơi buồn cười là agent đã thực hiện thành công cuộc tấn công một cách trọn vẹn
Một tuần trước tôi cũng thử coding agent Jules của Google, và yêu cầu quyền GitHub OAuth đòi quyền truy cập toàn diện tới mọi repository và mọi quyền trong tài khoản. Thiết kế kiểu này một phần là vì sự tiện lợi cho nhà phát triển, nhưng cũng do chính flow xác thực GitHub OAuth. Đúng ra ngay từ đầu phải cho phép cấp quyền giới hạn theo từng repository một cách thuận tiện hơn, rồi sau đó yêu cầu thêm quyền nếu cần. Nhưng thực tế hiện nay gần như buộc phải tạo một tài khoản GitHub riêng chỉ để cấp quyền cho một repository cụ thể (ví dụ tài khoản). Rất phiền. Tài liệu chính thức của GitHub cũng khuyến nghị tạo các machine user như vậy, nhưng lẽ ra việc đặt phạm vi repository mặc định phải dễ hơn. Nếu ai biết cách tốt hơn thì rất mong được chỉ cho
Tôi thấy lập luận của bài này bị thổi phồng quá mức. Với mô tả là chỉ qua một issue đơn giản mà đã làm rò rỉ dữ liệu, thì thực ra điều đó chỉ xảy ra khi người dùng tự mình thực hiện hàng loạt bước rủi ro về bảo mật. Tức là phải dựng MCP server, cấp credential cho cả public/private repo, cho phép LLM truy cập server đó và đọc issue của repository, rồi còn trực tiếp đọc cả issue độc hại, và cấu hình để công khai kết quả ra bên ngoài thì mới xảy ra được. Đây đúng là kết quả xấu, nhưng khó mà gọi là một “lỗ hổng bảo mật bị kẻ khác tấn công” theo nghĩa thông thường. Đó là hệ quả của việc người dùng tự để hệ thống đọc dữ liệu không đáng tin và cũng tự để kết quả đi ra nơi không đáng tin. Dù vậy GitHub MCP cũng có phần trách nhiệm. Việc không ngăn xử lý chéo giữa repository công khai và riêng tư là có vấn đề
Về bản chất, không nên bỏ qua chuyện chỉ với một lệnh đơn giản như “hãy tóm tắt các issue”, các chỉ dẫn độc hại được nhúng trực tiếp trong issue vẫn có thể bị thực thi
Góc nhìn marketing MCP cũng quan trọng. Bản thân giao thức nên được tách ra để chỉ những môi trường hay người dùng đáng tin mới có thể truy cập. Vấn đề là không có cách tiêu chuẩn để định scope hay xác thực ở cấp MCP server. Tôi thấy vấn đề gốc không nằm ở GitHub MCP riêng lẻ mà ở cách toàn ngành của chúng ta đang sử dụng/triển khai. Thực tế khi dùng custom MCP server, người ta thường truyền thêm cả thông tin ngoài AI như ID, JWT v.v. để chặn bảo mật
Vì cơn sốt AI hiện nay, thực tế có rất nhiều người áp dụng những cấu hình và luồng làm việc nguy hiểm như thế này mà không suy nghĩ nhiều. Ta có thể dễ dàng nói “đừng dùng như vậy”, nhưng chính vì con người thường đưa ra quyết định rủi ro nên mới cần guardrails
Với ý kiến nói rằng không nên trộn public/private repository, thì thực tế đây là hai lệnh gọi công cụ hoàn toàn tách biệt. Từ góc nhìn của MCP server, không có cách nào để phát hiện sự tương tác đó
Tôi nhận ra là cuộc thảo luận hiện đang diễn ra ở thread HN này
Bên đó cũng đã nhắc rồi, nhưng rủi ro bảo mật thì rất rõ: nếu cấp cho hệ thống quyền truy cập dữ liệu riêng tư, đồng thời cho phép người dùng bên ngoài đưa vào văn bản đầu vào tùy ý, thì rốt cuộc chẳng khác nào gián tiếp cung cấp dữ liệu riêng tư cho người ngoài. Đây là vấn đề có thể ngăn rất dễ nếu chỉ cần tuân thủ các thực hành bảo mật tiêu chuẩn
Các comment hiện đã được chuyển và tập trung ở đây
MCP chỉ là một giao thức; còn có A2A và nhiều trường hợp tương tự hay các cách tiếp cận thô hơn nữa. Bạn hoàn toàn có thể cho LLM đọc tài liệu GitHub API rồi bảo nó dùng token để gọi API. Hiện chưa phải mọi LLM đều có mức năng lực đó, nhưng sớm muộn cũng sẽ có. Việc bảo vệ tuyệt đối cơ chế đăng ký công cụ gần như bất khả thi trong thực tế. Trách nhiệm cuối cùng với việc rò rỉ dữ liệu rốt cuộc vẫn nằm ở LLM. Các nhà phát triển muốn LLM tăng năng suất, nên hoặc phải bảo đảm an toàn, hoặc rồi sẽ đến mức phải thêm firewall bảo mật vào mọi chiếc laptop. Điều thật đau đầu là trong tương lai có khi còn xuất hiện cảnh LLM xấu lợi dụng cả firewall bảo mật, dẫn tới cuộc đối đầu “LLM bắt LLM hành xử xấu” nữa cũng nên