Safety & Guard Rails
Guard rails: lớp phanh giữa model và hành động
Guard rail không làm model thông minh hơn — nó kiểm tra hành động trước khi tool thật sự chạy. Bài này mổ xẻ 4 lớp guard, 7 nhóm guard rail và những chỗ vẫn hở trong ClaudeKit.
Case: task nhỏ, quyền quá rộng
Giao agent một việc nhỏ: sửa validation trong một module. Nó quét thêm vài thư mục cho chắc, mở file config nhạy cảm, rồi tiện tay gom vài cleanup không liên quan vào cùng một PR. Test vẫn pass — nhưng context đã lẫn file rác, secret có thể đã vào transcript, review thì loãng.
Không guard rail
- Glob quá rộng, context bẩn
- cat .env, secret vào transcript
- Cleanup ngoài scope, review loãng
- Test pass nên ship luôn
Có guard rail
- scout-block exit 2, gợi ý thu hẹp pattern
- privacy-block exit 2 + hỏi user approval
- rule / hard-gate kéo về task chính
- simplify / review gate soi lại diff trước ship
Guard rail vs lời dặn trong prompt
| Khía cạnh | Guard rail | Lời dặn trong prompt |
|---|---|---|
| Chạy ở đâu | Harness, ngoài model | Trong context, model đọc |
| Ép buộc | Code chặn thật (block tool) | Model tự nguyện tuân |
| Khi context dài | Vẫn chạy | Dễ bị quên / trượt |
| Khi model hiểu lệch | Vẫn chặn (nếu không crash) | Lệch theo model |
| Sửa đổi | Cần đụng code/config | Sửa text là xong |
Hai thứ không loại trừ nhau. Việc rủi ro cao dùng guard rail; việc mang tính phong cách (commit format, comment convention) thì lời dặn là đủ.
4 lớp guard
Hook (code) Chặn thật Script harness tự gọi tại các mốc lifecycle. Trả exit 2 thì tool KHÔNG chạy. Đây là lớp chặn thật duy nhất.
Nhưng fail-open: hook crash thì Claude Code cho qua, guard tắt âm thầm.
Rule (CLAUDE.md) Lời dặn Text được inject vào context mỗi prompt. Định hướng hành vi, dễ thêm/sửa, không cần redeploy.
Không có exit 2 nào ép. Model mạnh tuân tốt hơn, prompt user có thể đè.
Hard-gate (XML) Lời dặn mạnh <HARD-GATE> nằm trong skill markdown, giữ trình tự (code trước plan, ship trước review). Signal mạnh hơn rule thường.
Vẫn là lời dặn, không phải hook. Có dòng "User override".
Guard skill (user gọi) User chủ động Chạy khi user gõ slash command: /ck:security-scan, /ck:predict, /ck:scenario, /ck:ship.
Không gọi thì không chạy. Là lớp chủ động, không tự động.
Flow một tool call qua guard
Exit code quyết định chặn hay không
exit 0 Cho chạy Tool chạy bình thường. stdout đọc làm JSON output.
exit 2 Chặn thật Tool không chạy. Bỏ stdout, đẩy stderr về model làm thông báo lỗi.
exit 1 / khác Lỗi, KHÔNG chặn Báo lỗi rồi tool VẪN chạy tiếp. Dùng nhầm exit 1 = guard tưởng bật mà thực ra mở.
Chỉ exit 2 mới chặn thật. Hook muốn enforce policy phải dùng đúng exit 2.
7 nhóm guard rail trong CK
| Nhóm | Cơ chế | Ví dụ | Ép buộc |
|---|---|---|---|
| Chặn file/path | PreToolUse | scout-block | Code, fail-open |
| Chặn sai bước | UserPromptSubmit | simplify-gate | Code |
| Thêm context | UserPromptSubmit | dev-rules-reminder | Code |
| Giữ tên sạch | Pre/Post/Stop | descriptive-name | Code, nhắc |
| Hard-gate skill | XML markdown | <HARD-GATE> | Lời dặn |
| Rule lời dặn | CLAUDE.md | review-audit | Lời dặn |
| Guard skill | User gọi | ck:security-scan | User |
Bốn hook đáng soi kỹ
scout-block Agent đọc node_modules/, glob **/*.ts ở root, cat dist/ — đốt token, context bẩn.
privacy-block Agent đụng .env, id_rsa, *.pem — secret lộ vào transcript. Exit 2 + bắt AskUserQuestion.
simplify-gate Diff phình > 400 LOC / > 8 file / 1 file > 200 LOC khi prompt có ship/merge/pr/deploy.
workflow-artifact-gate Kiểm 5 file JSON (context, risk, verification, review, adversarial) trước ship/push/pr/deploy.
Đọc trạng thái hook theo 3 nhãn
script file File .cjs có nằm trong .claude/hooks/. Có file CHƯA nghĩa là hook đang chạy.
wired settings.json đã gắn script vào lifecycle event. Không wire thì Claude Code không gọi.
runtime flag Khi đã được gọi, code đọc .ck.json / default / ENV để quyết có chạy tiếp không (vd: privacyBlock, simplify.gate.enabled).
isHookEnabled() chỉ tắt khi hooks.<name> là false. Key thiếu thường xem là enabled. Đừng gom mọi thứ thành "mặc định bật/tắt".
8 chỗ vẫn hở (known gaps)
- 1 File-access guard nằm ở hook (scout-block / privacy-block), không phải permissions.deny riêng.
- 2 Bash được miễn privacy-block — chỉ warn, không qua approval flow.
- 3 workflow-artifact-gate cần opt-in. Gate mạnh nhất không chạy nếu chưa bật.
- 4 simplify-gate mặc định chưa chặn. Cần bật simplify.gate.enabled rõ ràng.
- 5 simplify-gate trượt bằng phrasing — "ship on Friday" được bỏ qua.
- 6 .ckignore có thể negate node_modules bằng ! allowlist. Kiểm tra trực tiếp.
- 7 Rule là lời dặn — Claude có thể lệch khi prompt user đè.
- 8 HARD-GATE XML cũng là lời dặn, có "User override". Không có exit 2 nào ép.
Và: không có rate-limit / quota guard. Agent mất kiểm soát có thể call hàng nghìn Read/Bash; giới hạn nằm ở Claude Code / provider / billing, không ở guard rail.
6 câu kiểm tra trước khi tin guard rail
- settings.json đang gắn hook nào vào lifecycle nào?
- .ck.json đã disable hook nào? (cả outer + inner config)
- Session Claude Code hiện tại có đang bỏ qua permission prompt không?
- Có project .ckignore override không? node_modules có bị ! allowlist không?
- Rule files trong CLAUDE.md có đầy đủ không?
- Có hook nào đang crash âm thầm trong session này không (check stderr)?
Snapshot theo Engineer Kit stable claudekit-engineer@2.19.1. Bản 2.19.2-beta đang chuẩn bị bỏ 2 hook Agent Teams, nên danh sách hook có thể đổi khi upstream release version mới.
Đọc bài viết đầy đủ
Đọc bản đầy đủ với bản đồ ClaudeKit hooks theo lifecycle, snippet settings.json / .ck.json, cơ chế từng hook và phân tích sâu các gap →