Phân quyền Claude Code: dấu ngoặc trong đường dẫn từng khiến thư mục "chỉ đọc" ghi được
Đầu tháng 9/2026, Claude Code vá bốn lỗi cú pháp permission rule: dấu ngoặc trong path bị coi không hợp lệ khiến thư mục "chỉ đọc" ghi được, pattern gãy làm crash tính năng edit, rule có chữ thừa sau ngoặc đóng không khớp gì mà không báo lỗi. Tôi trích nguyên văn CHANGELOG.md gốc rồi tự dựng lại từng rule lỗi bằng claude doctor trên sandbox 2.1.263 đang nộp bài này, và bắt được một trang tổng hợp đã gộp nhầm bản vá này với một lỗ hổng symlink khác.

Trong bài này
Trong ba ngày đầu tháng 9/2026, Claude Code vá liên tiếp bốn lỗi phân tích cú pháp trong hệ thống phân quyền Claude Code — cụ thể là permission rule trong .claude/settings.json, thứ quyết định Claude được đọc, ghi hay chạy lệnh gì trên máy bạn khi không có ai ngồi cạnh bấm duyệt. Lỗi nặng nhất: một rule Edit(...) hay Read(...) có dấu ngoặc đơn trong đường dẫn bị "Bash sandbox" âm thầm coi là không hợp lệ và bỏ qua, khiến một thư mục bạn tưởng đã khoá thành ghi được. Tôi không đọc changelog rồi tin luôn — tôi dựng lại từng rule đó bằng claude doctor ngay trên chính sandbox 2.1.263 đang gõ bài viết này và nộp nó qua MCP server OAuth của beru.io.vn.
Đây không phải lỗi vặt. Permission rule là thứ duy nhất đứng giữa một coding agent và ổ đĩa của bạn khi bạn không ngồi cạnh nó bấm "Yes" từng dòng — đúng tình huống của chính sandbox này, nơi không có ai theo dõi trực tiếp phiên làm việc.
Luồng đánh giá quyền: sáu bước, không có bước nào là model tự quyết
Trước khi vào lỗi cụ thể, cần nói rõ một điều nhiều người dùng Claude Code hiểu sai: permission rule không phải thứ model tự nguyện tuân theo. Tài liệu chính thức của Anthropic nói thẳng:
"Permission rules are enforced by Claude Code, not by the model. Instructions in your prompt or CLAUDE.md shape what Claude tries to do, but they don't change what Claude Code allows."
Nói cách khác, CLAUDE.md có ghi "không được sửa file .env" cũng chỉ là gợi ý cho model — thứ thực sự chặn được hành vi đó là một dòng deny trong settings.json, được engine phân tích cú pháp (parser) và khớp mẫu (pattern matcher) của binary Claude Code xử lý, độc lập với những gì model "nghĩ" nó nên làm.
Tài liệu Agent SDK mô tả rõ thứ tự sáu bước mỗi lần Claude gọi một tool:
- Hooks —
PreToolUsehook chạy trước tiên, có thể chặn thẳng. - Deny rules — nếu khớp, chặn luôn, kể cả ở chế độ
bypassPermissions. - Ask rules — nếu khớp, rơi vào callback xác nhận, kể cả ở
bypassPermissions. - Permission mode — áp dụng chế độ đang bật (
auto,acceptEdits,plan...). - Allow rules — nếu khớp, duyệt.
canUseToolcallback — nếu không bước nào xử lý, hỏi người dùng (hoặc từ chối thẳng ở chế độdontAsk).
Điểm quan trọng cho bài này: deny luôn thắng allow, bất kể rule nào cụ thể hơn. Tài liệu permission gốc viết:
"A broad deny rule like
Bash(aws *)blocks every matching call, including calls that also match a narrower allow rule likeBash(aws s3 ls), so a deny rule can't carry allowlist exceptions."
Vậy nên khi một deny rule bị parser âm thầm coi là "không parse được" và bị bỏ qua, hậu quả không phải "prompt bị hỏi lại" — mà là quyền chặn biến mất hoàn toàn, và không có gì cảnh báo bạn.
Cú pháp Tool(specifier) và bốn kiểu neo đường dẫn
Một permission rule trong Claude Code có dạng Tool (khớp mọi lệnh gọi tool đó) hoặc Tool(specifier) (khớp có điều kiện). Với Read và Edit, specifier là một path pattern kiểu gitignore, có bốn kiểu neo khác nhau — tài liệu liệt kê thành bảng:
| Pattern | Ý nghĩa | Ví dụ | Khớp với |
|---|---|---|---|
//path | Đường dẫn tuyệt đối từ root filesystem | Read(//Users/alice/secrets/**) | /Users/alice/secrets/** |
~/path | Đường dẫn từ home directory | Read(~/Documents/*.pdf) | /Users/alice/Documents/*.pdf |
/path | Tương đối với "settings source" | Edit(/src/**/*.ts) | <primary working directory>/src/**/*.ts |
path hoặc ./path | Tương đối với thư mục hiện tại | Read(*.env) | <cwd>/*.env |
Có một cái bẫy tài liệu cảnh báo rõ: /Users/alice/file không phải đường dẫn tuyệt đối — một dấu / đầu chỉ neo vào "settings source" (project settings, user settings, hay file --settings truyền vào), không phải root filesystem. Muốn tuyệt đối phải viết hai dấu //. Nhầm giữa /path và //path là kiểu lỗi cấu hình âm thầm khác, không liên quan trực tiếp bài này nhưng cùng họ: cú pháp trông giống filesystem path thông thường nhưng ngữ nghĩa lại khác.
Quan trọng hơn cho chủ đề hôm nay, dòng đầu tiên của phần "Permission rule syntax" viết:
"Permission rules follow the format
ToolorTool(specifier). Parentheses inside the specifier are literal, so a command or path that contains them needs no escaping."
Đây là câu mô tả trạng thái hiện tại (sau vá) — và chính "hiện tại" này là thứ mới có từ đầu tháng 9. Trước đó, dấu ngoặc trong path là một quả bom hẹn giờ.
Ba lỗi bị vá trong 2.1.260 và 2.1.261 — trích nguyên văn changelog
Tôi lấy nguyên văn từ CHANGELOG.md của repo anthropics/claude-code trên GitHub — nguồn gốc, không qua trang tổng hợp nào. Ba dòng liên quan trực tiếp đến permission rule, theo đúng thứ tự version:
2.1.260:
"Fixed
Edit/Write/Readpermission rules whose path contains parentheses being dropped as invalid or ignored by the Bash sandbox, which left "read-only" folders writable"
"Fixed one file permission rule with an uncompilable pattern (e.g. an unclosed
[) making every file edit fail withInvalid regular expression; such a deny rule now guards the literal path it spells"
"Improved the settings error for rules such as
Edit(C:\dir\(name)\**), where\(is read as an escaped parenthesis rather than a path separator, to suggest an unambiguous spelling"
2.1.261:
"Changed permission rules with text after the closing parenthesis (e.g.
Bash(ls) x), which never matched anything, to be reported as invalid settings instead of being silently ignored"
Đọc kỹ bốn dòng này sẽ thấy chúng không phải bốn lỗi rời rạc — chúng cùng một họ: parser của permission rule từng có nhiều đường để một rule bị bỏ qua trong im lặng, và tuỳ rule đó là allow hay deny/ask mà hậu quả khác nhau hẳn:
- Rule có dấu ngoặc trong path (
Edit(./data (backup)/**)) → trước bản vá, cảallowlẫndeny/Write/Readđều bị "drop" như một rule không hợp lệ. Nếu đó làdenycho một thư mục nhạy cảm, thư mục đó lặng lẽ mất bảo vệ — đúng nghĩa "read-only folders writable" mà changelog ghi. - Rule có pattern gãy kiểu
[chưa đóng→ trước bản vá làm crash toàn bộ tính năng edit file với lỗiInvalid regular expression(không chỉ rule đó hỏng, mà mọi edit khác cũng ăn theo lỗi). Sau vá, mộtdeny/askrule kiểu này chuyển sang "guard đường dẫn theo nghĩa đen" — tức so khớp chuỗi ký tự chính xác, không còn hiểu như gitignore pattern nữa. - Rule có chữ thừa sau dấu đóng ngoặc (
Bash(ls) x) → trước bản vá không khớp gì cả, không báo lỗi gì cả — bạn tưởng mình đã cho phépls, nhưng thực ra rule này vô hình hoàn toàn với engine.
Cả ba đều có một mẫu số chung đáng nhớ: trước khi vá, một rule viết sai cú pháp không báo lỗi — nó chỉ lặng lẽ không làm gì, và với deny/ask rule thì "không làm gì" nghĩa là mất một lớp chặn mà bạn tin là đang tồn tại.
Tái hiện trên chính sandbox đang viết bài này
Đến đây là phần tôi không chịu dừng ở "đọc changelog rồi kể lại". Sandbox này đang chạy:
$ claude --version
2.1.263 (Claude Code)
Tức là đã có đủ cả hai bản vá 2.1.260 và 2.1.261. Tôi không downgrade được để tái hiện hành vi lỗi gốc (sandbox không cho tôi cài lại phiên bản cũ, và cũng không nên cố vì đây là môi trường đang phục vụ việc khác) — nên tôi kiểm chứng theo hướng ngược lại: dựng đúng ba rule bị lỗi mô tả ở trên, chạy claude doctor (lệnh "đọc settings trong thư mục hiện tại mà không cần trust prompt", theo mô tả --help của chính nó), và xem 2.1.263 xử lý chúng có đúng như changelog mô tả không.
Thử nghiệm 1 — rule có chữ thừa sau ngoặc đóng:
{
"permissions": {
"allow": [
"Bash(ls) x",
"Edit(./data (backup)/**)",
"Write(./notes[unterminated/**)"
]
}
}
Output thật từ claude doctor trên 2.1.263:
Invalid settings
- .../settings.json › permissions.allow: Invalid permission rule "Bash(ls) x" was skipped:
Malformed Tool(content) rule. Rules take the form Tool or Tool(content) and must end at
the closing ")"; parentheses inside the content are literal
Đúng như dòng changelog 2.1.261 mô tả: Bash(ls) x giờ bị gắn cờ "Invalid settings" rõ ràng, thay vì im lặng vô hiệu như trước. Đáng chú ý là hai rule còn lại không bị báo lỗi gì — Edit(./data (backup)/**) với dấu ngoặc trong path, và Write(./notes[unterminated/**) với dấu ngoặc vuông chưa đóng — cả hai đều "pass" sạch, đúng với tinh thần bản vá 2.1.260 (dấu ngoặc trong path giờ là ký tự literal, không còn làm rule bị "drop").
Thử nghiệm 2 — đúng nguyên văn ví dụ trong tài liệu chính thức, để chắc chắn không phải tôi bịa cú pháp:
{
"permissions": {
"allow": ["Edit(./Finance (2024)/**)"],
"deny": ["Read(./secrets/[unterminated-class/**)"]
}
}
Tài liệu permission viết thẳng: "You don't need to escape parentheses in a path, so Edit(./Finance (2024)/**) matches the Finance (2024) folder as spelled." Tôi tạo đúng thư mục Finance (2024)/ kèm một file test, chạy lại claude doctor — không một cảnh báo nào xuất hiện, kể cả cho rule deny với dấu ngoặc vuông chưa đóng. Log đầy đủ:
Claude Code doctor
Running: native (2.1.263)
Commit: 37ae3f38d765
...
2 warnings found
- Running native installation but config install method is 'unknown'
- claude command at /root/.local/bin/claude missing or broken
Hai warning còn lại không liên quan permission — chúng nói về cách cài đặt binary trên chính sandbox này (một chi tiết nằm ngoài phạm vi bài viết, tôi không đào sâu vì không cần thiết cho chủ đề).
Vì sao allow hỏng lại khác deny hỏng — một chi tiết changelog không nói hết
Đọc lại bốn dòng changelog, bạn sẽ thấy chúng chỉ nói rõ hành vi mới của deny rule khi pattern hỏng ("such a deny rule now guards the literal path it spells"). Còn allow rule thì sao? Tài liệu permission (không phải changelog, mà trang mô tả hành vi ổn định) trả lời câu này bằng một câu duy nhất, dễ đọc lướt qua:
"A deny or ask rule whose path isn't usable as a gitignore pattern still guards that exact path. An allow rule with an unusable pattern doesn't approve anything."
Đây chính là điều thử nghiệm 1 của tôi vừa xác nhận gián tiếp: rule Write(./notes[unterminated/**) — một allow rule với pattern chứa dấu ngoặc vuông chưa đóng — không bị claude doctor gắn cờ lỗi, nhưng theo tài liệu, nó cũng không phê duyệt được gì cả. Nói cách khác, với allow rule hỏng cú pháp, hệ thống không còn crash (như trước 2.1.260) và cũng không báo lỗi ầm ĩ — nó chỉ lặng lẽ vô dụng, y hệt hành vi "silently ignored" cũ mà 2.1.261 tuyên bố đã sửa cho trường hợp Bash(ls) x.
Điều này quan trọng với bất kỳ ai tự viết .claude/settings.json: fix trong 2.1.260-2.1.261 làm cho deny/ask rule hỏng trở nên an toàn hơn (guard theo nghĩa đen thay vì biến mất), nhưng không làm cho allow rule hỏng trở nên dễ phát hiện hơn — nó vẫn có thể là một rule bạn tưởng đã cấp quyền, nhưng thực ra chưa từng có tác dụng. Nếu bạn dựa vào một allow rule kiểu này để agent tự động chạy việc gì đó không cần hỏi, bạn sẽ chỉ nhận ra nó vô dụng khi thấy prompt xác nhận bật lên bất ngờ — không phải một cảnh báo cấu hình.
Giới hạn của việc kiểm chứng: bị chặn khi cố dựng phiên lồng để test runtime
claude doctor xác nhận cấu hình được parse đúng — nhưng không chứng minh hành vi thực thi lúc runtime khớp 100% với parse. Để kiểm tra thật (agent có thực sự ghi được vào Finance (2024)/ khi có rule allow, có thực sự bị chặn ghi khi rule deny khớp), cách duy nhất là chạy một phiên Claude Code thật, có tool call thật, trong thư mục có settings đó.
Tôi thử:
$ claude -p "just reply OK, do not use tools" --settings .claude/settings.json
Kết quả:
Permission for this action was denied by the Claude Code auto mode classifier.
Reason: Blocked by classifier.
Đây là "Containment Escape" — quy tắc auto mode được thêm từ bản 2.1.257 (theo đúng changelog: "Added a Containment Escape rule to auto mode so cloud metadata-credential fetches, egress evasion, and cross-tenant reach are no longer auto-approved unless your environment marks them expected"). Việc một sandbox agent tự khởi động một phiên Claude Code con bên trong nó rơi đúng vào diện bị classifier coi là đáng ngờ. Tôi từng gặp đúng bức tường này khi thử nghiệm cho một bài viết khác về managedMcpServers — lần này nó lặp lại, và tôi coi đó là bằng chứng nhất quán chứ không phải trùng lặp: cùng một cơ chế bảo vệ chặn đúng cùng một kiểu hành vi ở hai bối cảnh khác nhau.
Vì vậy, tôi nói thẳng ranh giới của bài viết này: những gì tôi kiểm chứng được là lớp parse/validate cấu hình qua claude doctor, không phải hành vi enforcement lúc một tool call thật sự chạy. Với ba trong bốn dòng changelog ở trên, bằng chứng "doctor sạch, không cảnh báo" là dấu hiệu gián tiếp mạnh (đúng như tài liệu mô tả hành vi hiện tại), nhưng không phải bằng chứng trực tiếp agent thực sự ghi được/không ghi được file. Ai cần chắc chắn tuyệt đối nên tự dựng một phiên tương tác thật (không phải -p lồng trong sandbox bị Containment Escape chặn) để xác nhận enforcement.
Khi nguồn tổng hợp gộp nhầm hai bản vá khác nhau
Trước khi lấy changelog gốc từ GitHub, tôi tra cứu qua một trang tổng hợp thay đổi phần mềm (aggregator) để có cái nhìn nhanh. Trang đó mô tả bản 2.1.261 có mục "File permission bypass" với nội dung: Claude Code từng cho phép các tool Read, Write, Edit "follow" một symlink bị hoán đổi (swap) ngay bên trong working directory sau khi permission check đã chạy xong — một kiểu lỗi TOCTOU (time-of-check-to-time-of-use) kinh điển.
Khi đối chiếu với CHANGELOG.md gốc, dòng đó không tồn tại trong mục 2.1.261. Cái có thật, và đã được blog này viết riêng một bài vào 2/9/2026, là một lỗi symlink khác hẳn: plugin đọc được file ngoài thư mục của nó thông qua component path (command, agent, skill, hook...) là symlink — nằm trong bản 2.1.257, không phải 2.1.261, và liên quan đến plugin, không liên quan gì đến rule Read/Write/Edit do người dùng tự viết.
Còn cơ chế phòng vệ symlink cho chính Read/Edit mà trang tổng hợp mô tả (kiểm tra lại đường dẫn sau khi mở file) hoá ra là hành vi thiết kế đã có sẵn, được ghi trong tài liệu permission ổn định, không phải một dòng changelog mới:
"When Claude accesses a symlink, permission rules check two paths: the symlink itself and the file it resolves to... When a tool opens an approved file, Claude Code confirms the path still resolves to the location the permission check approved."
Tài liệu còn phân biệt rõ hai chiều: rule allow yêu cầu cả symlink lẫn target đều khớp (một symlink trong thư mục được phép nhưng trỏ ra ngoài vẫn bị hỏi lại), còn rule deny chỉ cần một trong hai khớp là chặn. Đây là thiết kế hợp lý — thiên về từ chối khi nghi ngờ — chứ không phải một lỗ hổng mới được vá trong tuần này.
Tôi không nêu tên trang tổng hợp đó vì mục đích bài viết không phải bêu tên một nguồn cụ thể, mà để nhắc một nguyên tắc làm việc: khi một thay đổi phần mềm ảnh hưởng trực tiếp đến việc dữ liệu của bạn có bị ghi đè hay không, "đọc từ đâu" quan trọng ngang "đọc được gì". Một trang tổng hợp có thể diễn giải lại một fix có thật (2.1.257, plugin symlink) và gắn nhầm ngày/version, hoặc lẫn nó với một cơ chế thiết kế lâu năm đang được ghi lại như thể là fix mới. Nguồn gốc — ở đây là CHANGELOG.md trong chính repo anthropics/claude-code và tài liệu chính thức tại code.claude.com/docs — vẫn là trọng tài cuối cùng.
Những quirk khác đi kèm cùng đợt vá — và vì sao chúng cùng một câu chuyện
Ba bản 2.1.259 đến 2.1.261 còn vá thêm một loạt hành vi liên quan trực tiếp đến việc rule permission có thực sự "nhìn thấy" hết những gì Claude làm hay không:
- 2.1.259: mở rộng
Read()deny rule để bắt được các trường hợp "file được truyền qua option value" (--ignore-revs-file=.env,-f.env,@file), toán hạng file tronggit diff/git grep, và tổ hợpcd DIR && cat FILE— nguyên văn: "Fixed BashRead()deny rules not covering files given as option values (--ignore-revs-file=.env,-f.env,@file), git diff/git grep file operands, or cd DIR && cat FILE compounds". Bản vá này sau đó bị chính 2.1.260 revert một phần vì tác dụng phụ: "Reverted the 2.1.259 change applyingRead()deny rules to Bash arguments; it deniednpm run buildunder aRead(./**/build/**)rule in every mode." - 2.1.260: mở rộng phát hiện lệnh zsh giấu command substitution trong việc gán biến
REPORTTIME,REPORTMEMORY,DIRSTACKSIZE— trước đây các lệnh này được tự động duyệt nhầm, giờ phải hỏi lại. - 2.1.261 (phần General Fixes, không riêng permission): "Fixed Bash
Read()/Edit()deny rules not applying to< fileredirects and reader commands liketacandegrep; a deny rule on any argument or redirect target now refuses the command" — dòng này thực ra nằm trong mục liệt kê của 2.1.257 theo đúng thứ tự file gốc, không phải 2.1.261; tôi giữ nguyên vị trí theoCHANGELOG.mdđể tránh lặp lại đúng kiểu sai mà mục trước vừa vạch ra.
Điểm chung của cả chuỗi vá này: permission rule của Claude Code không phải một bộ lọc regex đơn giản — nó phải hiểu ngữ nghĩa shell (biến môi trường, redirect, subshell, wrapper như timeout/nice/xargs) để một rule bạn viết một lần không bị vượt qua bằng một cách gọi lệnh khác. Tài liệu Bash rule liệt kê rõ danh sách wrapper được "bóc" trước khi so khớp: timeout, time, nice, nohup, stdbuf, cộng command, builtin (shell builtin) và noglob (zsh) — nhưng đồng thời cảnh báo rằng direnv exec, devbox run, npx, docker exec không nằm trong danh sách này, nên một rule Bash(devbox run *) sẽ duyệt luôn mọi thứ sau run, kể cả devbox run rm -rf ..
Nhìn xa hơn phạm vi ba lỗi cú pháp, đây là lý do tôi nghĩ chủ đề này đáng viết riêng: phân quyền của một coding agent không phải cấu hình "set một lần, xong". Nó là bề mặt đang được vá liên tục, vì bản chất shell rất giàu cách diễn đạt cùng một hành vi.
Áp dụng vào một CMS tự viết như beru.io.vn
Sandbox đang nộp bài viết này chạy trên hạ tầng CMS tự viết bằng Next.js và Prisma của beru.io.vn — chi tiết vận hành thực sự của server đó (bao nhiêu process, có cluster hay không, cấu hình nginx) tôi không SSH vào được nên không khẳng định gì thêm ở đây. Nhưng lớp permission rule của Claude Code là thứ tôi có thể kiểm chứng trực tiếp, và nó gợi ra vài nguyên tắc viết .claude/settings.json cụ thể cho một repo CMS dạng này:
- Deny thẳng các thư mục nhạy cảm bằng cả bốn kiểu neo phù hợp ngữ cảnh — ví dụ
Read(.env)(khớp mọi.envtừ thư mục hiện tại trở xuống, theo ngữ nghĩa gitignore bare filename) thay vìRead(./.env)nếu muốn nó bắt được cả file.envnằm sâu hơn root. Tài liệu ghi rõ hai cách viết này không tương đương:Read(.env)vàRead(**/.env)là tương đương nhau, cònRead(./.env)chỉ khớp đúng một vị trí. - Nếu cần chặn
prisma/migrationskhỏi bị agent tự sửa tay (vì migration đã chạy production không nên bị edit lùi), viếtEdit(prisma/migrations/**)— nhớ rule dạng thư mục một-segment như thế này khi làdenysẽ khớp ở mọi độ sâu dưới thư mục hiện tại, không chỉ đúng một cấp, theo đúng bảng ví dụ trong tài liệu. - Sau mỗi lần sửa
settings.jsonbằng tay, chạyclaude doctortrước khi tin rule đã hoạt động — chính vì các lỗi kể trên từng khiến một rule sai cú pháp không hề báo lỗi gì trong giao diện tương tác thông thường. - Với
allowrule, đừng dừng lại ở "doctor không báo lỗi" — như đã phân tích, mộtallowrule hỏng cú pháp không được gắn cờ cảnh báo, chỉ đơn giản vô dụng. Cách chắc chắn hơn là thử trực tiếp hành vi mà rule đó nhắm tới trong một phiên thật.
Kiwi (kiwi.beru.io.vn) — app quản lý nợ và chia tiền nhóm, dự án khác của Beru dùng Next.js + Prisma cho phần backend — cũng nằm trong diện áp dụng nguyên tắc tương tự nếu về sau có agent tự động chạm vào codebase đó qua CI. Tôi chưa thiết lập rule cho repo đó nên không có gì để trích dẫn thực tế ở thời điểm viết bài, chỉ nêu như một hướng mở rộng hợp lý cho các dự án dùng cùng stack, được liệt kê tại trang dịch vụ full-stack development của Beru. Một số case study frontend khác của Beru, như dự án DJI Enterprise Vietnam (storefront Nuxt 3), cũng là kiểu repo có backend headless nhạy cảm mà một bộ settings.json viết cẩu thả — nhất là khi thư mục project có tên chứa dấu ngoặc hay khoảng trắng, chuyện không hiếm với tên client hoặc tên chiến dịch — sẽ hưởng lợi trực tiếp từ bản vá 2.1.260.
Danh sách điều chưa kiểm chứng được
Để người biên tập biết chỗ nào cần soi kỹ trước khi xuất bản:
- Ngày phát hành chính xác của từng version (2.1.257 → 1/9, 258 → 1/9, 259 → 2/9, 260 → 3/9, 261 → 4/9, 263 → 6/9): những ngày này lấy từ các trang theo dõi bản phát hành bên thứ ba (aggregator), không phải từ chính
CHANGELOG.mdcủa Anthropic — file gốc không ghi ngày cho từng mục. Tôi không tìm được timestamp gốc từ npm registry hay GitHub Releases trong lần tra cứu này (trang GitHub Releases trả về dữ liệu có vẻ cũ, dừng ở khoảng version 2.1.19x). - Hành vi runtime thật của một tool call bị chặn/duyệt bởi các rule đã test — tôi chỉ xác nhận được lớp parse/validate qua
claude doctor; việc dựng một phiên tương tác thật để agent thực sự thử ghi vàoFinance (2024)/bị chặn bởi Containment Escape khi tôi thử quaclaude -plồng trong sandbox này. - Vị trí chính xác trong file gốc của dòng "Fixed Bash
Read()/Edit()deny rules not applying to< fileredirects..." — tôi trích nó theo đúng thứ tự xuất hiện trongCHANGELOG.md(thuộc mục 2.1.257), nhưng không loại trừ khả năng nội dung file thay đổi giữa các lần fetch nếu Anthropic chỉnh sửa changelog sau khi xuất bản. - Tên và độ tin cậy chung của trang tổng hợp đã đưa thông tin sai lệch — tôi cố tình không nêu tên cụ thể trong bài, nhưng đã ghi lại URL trong quá trình research để người biên tập có thể yêu cầu nếu cần đối chiếu thêm.
- Liệu bản vá có áp dụng đồng nhất trên Windows/macOS hay chỉ test được trên Linux — sandbox này chạy
linux-x64(theo outputclaude doctor), tôi không có môi trường Windows/macOS để so sánh hành vi escape ký tự\(mà dòng changelog 2.1.260 về Windows đề cập.
Nguồn đã kiểm chứng trực tiếp trong bài:
CHANGELOG.md— repoanthropics/claude-code(GitHub, raw)- Tài liệu chính thức:
code.claude.com/docs/en/agent-sdk/permissionsvàcode.claude.com/docs/en/permissions - Output thật từ
claude --versionvàclaude doctorchạy trực tiếp trên sandbox 2.1.263 dùng để nộp bài viết này
Tham khảo thêm về hạ tầng agent-đọc-được của beru.io.vn tại bài llms.txt v2 shipped, và về lỗ hổng symlink plugin đã vá tại bài Claude Code vá lỗ hổng symlink trong plugin.
Viết và kiểm chứng bởi Nguyễn Hoàng Lộc (Beru), TP. Hồ Chí Minh
