Bỏ qua để vào nội dung chính
Guard của Claude Code fail-open: một dòng catch đổi kết cục

Guard của Claude Code fail-open: một dòng catch đổi kết cục

Bởi Charlotte Adams
05 thg 10, 20266 phút đọc

Khi mod guard ném lỗi, Claude Code bỏ qua nó và lệnh vẫn chạy. Một handler .catch đảo lại hành vi đó, kèm cách audit quyền của mod đang cài.

Bạn cài một mod guard để chặn lệnh shell nguy hiểm, thấy nó xuất hiện trong danh sách plugin, rồi yên tâm quay lại làm việc. Một tuần sau guard đó ném exception vì một lỗi nhỏ — và lệnh vẫn chạy, không có cảnh báo nào. Bài này chỉ ra vì sao hành vi mặc định là như vậy, một dòng code để đảo nó lại, và cách kiểm tra mod bạn đang cài thực sự xin những quyền gì.

Guard ném lỗi thì bị bỏ qua — đó là hành vi có tài liệu

Một bài test công bố trên Dev.to mô tả thí nghiệm đơn giản nhất có thể: viết một mod theo dõi mọi lệnh shell mà Claude Code chuẩn bị chạy, và cho nó throw. Tác giả yêu cầu đúng một lệnh, touch ./marker-failopen.txt. Guard crash như thiết kế, log chỉ có một dòng:

failguard: tool.call hook skipped: threw Error: guard crashed

Và file vẫn nằm trong thư mục. Theo tài liệu mà bài viết trích lại, khi một hook không có .catch ném lỗi, timeout, hoặc trả về sai shape trước khi gọi next, thì "Claude Code skips it, and the next handler runs in its place." Với một mod trang trí thì hợp lý — heatmap hỏng không nên làm chết session. Với một guard, nó có nghĩa là thất bại diễn ra im lặng và lệnh được thực thi.

Một handler đổi fail-open thành fail-closed

Cách sửa nằm ngay trong cùng tài liệu đó và chỉ là một handler:

on('tool.call', { tool: 'Bash' }, guard)
  .catch(async ($, e, next) => {
    return { deny: 'The command guard failed, so this command was not run: ' + next.error.kind }
  })

Vẫn guard crash đó, vẫn prompt đó, nhưng có thêm catch: không file nào được tạo, và model báo lại là lệnh bị chặn. Nếu tuần này bạn có cài một mod an toàn nào đó, việc đầu tiên nên làm là mở nó ra và tìm xem có catch hay không.

Một chi tiết quan trọng cho ai định tin tuyệt đối vào pattern này: bài viết dẫn lại một lượt re-test của cộng đồng trên bản 2.1.288, 10 case × 3 lần chạy, chấm bằng marker file thay vì bằng lời model nói. Pattern catch giữ được kết quả, nhưng còn một đường hở — một deny trả về sau khi lời gọi đã được forward thì không chặn được tool nữa. Trong re-test đó, file vẫn được ghi 3/3 lần trong khi model được báo là thao tác ghi đã thất bại.

Mod không chạy trong sandbox, và permission rule không che nó

Đây là phần nhiều người cài mod chưa đọc kỹ. Bài viết trích phát biểu của Anthropic trong ngày ra mắt: "Mods run with the same access to your machine as Claude Code itself. They aren't sandboxed." Tài liệu nói thẳng hệ quả: "with Read(.env) denied, a mod can still read that file with $.fs.read or start a program that does." Nói cách khác, allow/deny list của bạn áp cho tool call của Claude, không áp cho bản thân mod.

Công cụ kiểm tra có sẵn: claude plugin validate in ra mod hook vào đâu, gọi những gì, và đọc biến môi trường nào. Tác giả chạy lệnh này với một mod bookmark và thấy audit liệt kê $.model.complete, $.process.run và $.fs.write — tức một mod lưu bookmark có quyền gọi model, chạy chương trình và ghi file. Tác giả nhấn mạnh không có gì độc hại trong mod đó; vấn đề là tầm với rộng hơn nhiều so với công việc nó làm.

Chi phí ẩn: mod được demo nhiều nhất tính tiền mỗi câu trả lời

Cũng trong tuần test đó (85 session, 4 project, 882 prompt, 5.993 tool call, đối chiếu baseline sạch trên Claude Code 2.1.288, trung vị ba lần chạy), tác giả đo mod gợi ý next-steps. Để sinh ba gợi ý sau mỗi lượt, mod fork session; README của nó nói fork dùng chung prompt cache nên "costs about one short reply". Số tác giả đo được:

Cấu hìnhThời lượngOutput token
baseline3.980 ms247
next-steps6.830 ms497
cache-keeper5.569 ms367

Khoảng 250 output token và 2,9 giây cộng thêm cho mỗi câu trả lời, theo phép đo của tác giả. Chi tiết đáng chú ý hơn: fork không có cổng chặn theo bề mặt hiển thị — tác giả thấy nó vẫn chạy trong một phiên headless claude -p, nơi không có gì để vẽ ra màn hình, và không có setting nào giữ gợi ý mà bỏ fork.

Khi nào hook shell vẫn đúng hơn mod

Mod chạy in-process nên không mất chi phí spawn tiến trình. Tác giả quy đổi chi phí đó trên 5.993 lời gọi: bash -c 'exit 0' tốn 8,3 ms mỗi lần, cộng dồn 50 giây; python3 -c 'pass' 26,1 ms, cộng dồn 156 giây; node -e '' 43,1 ms, cộng dồn 258 giây. Nghĩa là với khối lượng một tuần của một người, khác biệt là vài phút — chỉ đáng kể khi bạn ở mức hàng nghìn lời gọi mỗi ngày.

Quy tắc tác giả rút ra đáng mượn: viết lại giao diện hay event thì dùng mod; chặn, cho phép hoặc ghi log thì dùng script shell mà bạn đã đọc. Một hook bạn đã đọc tốt hơn một mod bạn chưa đọc.

Vì sao nên siết ngay bây giờ

Bối cảnh rộng hơn đến từ một bài phân tích khác: theo số liệu bài này dẫn từ một cuộc red-team công khai năm 2026, trong 272.000 lượt thử injection nhắm vào 13 AI agent frontier thì 8.648 lượt thành công, tỉ lệ dao động 0,5% đến 8,5% tùy model và không model nào trong bài test miễn nhiễm. Cũng theo nguồn đó, năng lực và độ bền trước injection gần như không tương quan — model mạnh nhất nằm trong nhóm dễ bị tấn công nhất. Đây là số liệu dẫn lại, không phải phép đo độc lập, nhưng hướng của nó đủ rõ: chọn agent theo benchmark không nói gì về bán kính thiệt hại khi nó bị lừa.

Checklist 10 phút cho máy của bạn

  • Liệt kê mod đang bật, chạy claude plugin validate cho từng cái và đọc dòng audit — đặc biệt là $.process.run và $.fs.write.
  • Mở mọi mod làm nhiệm vụ chặn, tìm .catch. Không có thì guard của bạn đang fail-open.
  • Tự kiểm chứng bằng marker file, đừng tin câu trả lời của model: cho guard crash có chủ đích rồi xem file có được tạo không.
  • Với luật chặn thật sự quan trọng, cân nhắc giữ ở tầng hook shell mà bạn tự viết và tự đọc được.

Giới hạn của bộ số trên, chính tác giả cũng nêu: một tuần, một máy, một khối lượng công việc, ba lần chạy cho mỗi điểm đo. Con số có thể khác trên máy bạn — phương pháp mới là thứ chuyển giao được. Thứ đáng theo dõi tiếp là đường hở deny-sau-forward: chừng nào nó còn đó, mọi guard đều nên được kiểm bằng marker file chứ không bằng log.

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

Bài viết liên quan