Repository navigation
fix(permissions): ignore NotADirectory and strip BOM before empty check - #4658
webdevsamran wants to merge 1 commit into
Conversation
|
|
📊 Automated PR Analysis
SummaryFixes the Claude Code settings permission loader to treat ErrorKind::NotADirectory the same as NotFound (so a non-directory parent like a Review Checklist
Linked issues: #4651 Analyzed automatically by wshm · This is an automated analysis, not a human review. |
houtinghang
left a comment
There was a problem hiding this comment.
I tested this locally. The fix does what #4651 asks, and the two new tests fail without it and pass with it. The one thing in the way is the conflict with develop.
Conflict with develop. #4127 (62cf6ba7, merged 10-23) moved this loop into load_permission_rules_tracking() and added a three-line comment above the NotFound arm. That is the only conflicting hunk: keeping the comment and taking your matches! arm resolves it, and the rest of the patch applies unchanged. This is the resolution I tested:
Ok(content) => content,
// A file that is not there denies nothing. One that is there and
// could not be read — permissions, or bytes that are not UTF-8 —
// may hold anything.
Err(e)
if matches!(
e.kind(),
std::io::ErrorKind::NotFound | std::io::ErrorKind::NotADirectory
) =>
{
continue;
}After the rebase the change also reaches claude_hook_deny_rules(), the gate for the opt-in fish wrap from #4127. Both new skips happen before scan.every_file_read = false, so a .claude regular file or a BOM-only settings file no longer forces that gate to Unattested. That matches the SettingsScan doc ("Every settings file that exists was opened, decoded and parsed"), but since the issue is labelled area:security it may be worth a line in the description. (This part is from reading the code; I did not exercise the wrap path.)
What I ran (WSL2 Ubuntu 26.04 x86_64, rustc 1.99.0, debug builds of the PR's merge base 9a501c8d, the PR head 1c85e65c, develop 32b2ec43, and develop + this PR with the conflict resolved as above):
rtk rewrite "git status" exit codes, with an isolated HOME and CLAUDE_CONFIG_DIR, and allow: ["Bash(git status)"] in the other settings file:
| case | base | PR | develop | develop + PR |
|---|---|---|---|---|
project .claude is a regular file |
3 | 0 | 3 | 0 |
settings.local.json = EF BB BF |
3 | 0 | 3 | 0 |
settings.local.json = EF BB BF + " \r\n" |
3 | 0 | 3 | 0 |
CLAUDE_CONFIG_DIR points at a regular file |
3 | 0 | 3 | 0 |
The .claude file, BOM-only and CLAUDE_CONFIG_DIR cases under RTK_REWRITE_HOST=openclaw, with git log (no rule matches), also go from 3 to 0. In all of these the Not a directory (os error 20) / failed to parse warnings are gone after the fix.
Controls, the same on all four builds: invalid JSON → 3, BOM + invalid JSON → 3, BOM + deny: ["Bash(git status)"] → 2, settings.local.json that is a directory → 3, non-UTF-8 bytes → 3, a plain allow file → 0. The controls still print their warnings.
cargo test --lib hooks::permissions: on the base and ondevelopwith only the two new tests added, 147 passed and the 2 new tests failed; with the fix, 149/149 on both.develop+ PR:cargo test --no-fail-fast4915 passed, 0 failed (developwith only the two tests added: 4913 passed, the 2 new tests failed).cargo fmt --all --checkandcargo clippy --all-targetsare clean on both the PR head and the rebased commit.- Not tested: Windows and macOS. Per the issue, Windows already reports
NotFoundfor the regular-file layout, sotest_not_a_directory_settings_file_adds_no_rulespasses there with or without the fix.
Two small things, neither blocking:
- The first summary bullet says non-directory parents now "fail closed". After this change they are skipped like a missing file; the catch-all
Askis what #4287 calls failing closed. Rewording it would keep the description from reading as the reverse of the change. - #4680 (for #4652) reworks
read_json()for the Cursor and Droid loaders with the sameNotFound-only arm and the sametrim()check before the BOM is stripped. Whichever of the two lands second may want to carry both checks there too.
AI disclosure: I used Claude Code to build the binaries, run the tests above and draft this comment, and I checked the results and the wording before posting.
Signed-off-by: Samran Asif <samranwebdev2000@gmail.com>
1c85e65 to
455ea7f
Compare
|
Hi @houtinghang, thank you so much for the thorough review and for running the extensive local test matrices across Ubuntu, WSL2, and RTK rewrite modes! Addressed in commit 455ea7f:
Verified with |
Summary
Test plan
AI Disclosure: Implementation assisted by agentic workflow; logic, bounds, and regression tests thoroughly inspected.