Repository navigation
Resolve the nearest existing folder in the hint guard - #86
Conversation
A write makes the missing folders of its path, so the folder that decides where it lands is the nearest one that exists. The guard now takes the real path of that folder, then adds the rest of the path. It does this for the path of the call and for each guarded folder, so a symbolic link in HOME, in the project or in a path to a new folder gives the same result. Version 0.12.18.
|
@greptile review |
1 similar comment
|
@greptile review |
[Medium impact] The change affects file-tool calls that target guarded hint, function, or installed-plugin folders. Restore the resolved-parent check before merging so existing file links cannot escape the hint-file guard. Findings
Fix with agent prompt### Issue 1
hooks/register.tsx:820-821
`landings` drops the resolved parent when an existing file is a symbolic link. For example, let `/repo/cm` link to `$HOME/.claude/code-mode`, and let its `hints/x.md` link to `/tmp/x.md`. A call on `/repo/cm/hints/x.md` now produces only the written path and `/tmp/x.md`. Neither matches a guarded folder, so the call passes. Previously, the resolved parent added `$HOME/.claude/code-mode/hints/x.md` and denied it.
Keep the resolved-parent candidate alongside the new ancestor check, and add an existing-file-link test. This also satisfies the instruction in `CODING_STANDARDS.md`: “Never weaken … the guard of hint and function files.”
**How this was verified:** For this link layout, the early return resolves the file outside the guarded folder, and neither remaining candidate names its protected parent.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
|
| const real = await realFormOf($, full) | ||
| return real === undefined ? [full] : [full, real] |
There was a problem hiding this comment.
Linked hint files escape denial
landings drops the resolved parent when an existing file is a symbolic link. For example, let /repo/cm link to $HOME/.claude/code-mode, and let its hints/x.md link to /tmp/x.md. A call on /repo/cm/hints/x.md now produces only the written path and /tmp/x.md. Neither matches a guarded folder, so the call passes. Previously, the resolved parent added $HOME/.claude/code-mode/hints/x.md and denied it.
Keep the resolved-parent candidate alongside the new ancestor check, and add an existing-file-link test. This also satisfies the instruction in CODING_STANDARDS.md: “Never weaken … the guard of hint and function files.”
How this was verified: For this link layout, the early return resolves the file outside the guarded folder, and neither remaining candidate names its protected parent.
Context Used: AGENTS.md (source)
Knowledge Base Used: Session startup and paths
Prompt To Fix With AI
This is a comment left during a code review.
Path: hooks/register.tsx
Line: 820-821
Comment:
**Linked hint files escape denial**
`landings` drops the resolved parent when an existing file is a symbolic link. For example, let `/repo/cm` link to `$HOME/.claude/code-mode`, and let its `hints/x.md` link to `/tmp/x.md`. A call on `/repo/cm/hints/x.md` now produces only the written path and `/tmp/x.md`. Neither matches a guarded folder, so the call passes. Previously, the resolved parent added `$HOME/.claude/code-mode/hints/x.md` and denied it.
Keep the resolved-parent candidate alongside the new ancestor check, and add an existing-file-link test. This also satisfies the instruction in `CODING_STANDARDS.md`: “Never weaken … the guard of hint and function files.”
**How this was verified:** For this link layout, the early return resolves the file outside the guarded folder, and neither remaining candidate names its protected parent.
**Context Used:** AGENTS.md ([source](https://github.com/gabe4coding/claude-code-mode/blob/main/AGENTS.md))
**Knowledge Base Used:** [Session startup and paths](https://app.greptile.com/gabe4coding/-/custom-context/knowledge-base/gabe4coding/claude-code-mode/-/docs/session-startup-and-paths.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.A hint file can itself be a symbolic link out of its folder. A write by a linked folder to that file then names a file in the hint folder, but the real form of the file is outside it. The guard now keeps the real form of the parent folder with the file name as one more place where the path can land, as it did before the nearest folder step. It also keeps the path as written and the real form of the file. Gabriele Pavanello gabry.pavanello@gmail.com
# Conflicts: # docs/hints.mdx
Intent
The hint guard resolves the nearest existing folder for paths that create new folders.
A write makes the missing folders of its path, so the nearest folder that exists decides where the file lands.
The guard now takes the real path of that folder and adds the rest of the path.
It does this for the path of the call and for each guarded folder.
%%{init: {'theme': 'neutral'}}%% flowchart TD A["The model calls Write, Edit or NotebookEdit"] --> B["Find the nearest folder of the path that exists"] B --> C["Take its real path and add the rest of the path"] C --> D["Do the same for each guarded folder"] D --> E{"Is the path inside a guarded folder?"} E -->|yes| F["Deny the call with the guard message"] E -->|no| G["Run the file tool"]Drift
None.
Decisions
statcalls stays small.readlink.Evidence
Head
319ba53on main548fddb. Treec3fe0023584429910799e977e736727fe980ead3.Real Claude Code 2.1.296 on Linux, with the plugin from a local git copy of the commit, in the permission mode that asks for no approval.
A scripted Messages API on localhost sends the Write calls, because the box has no Claude Code login. Claude Code, the plugin hooks, the Write tool and the file system are real.
The project has symbolic links to guarded folders, and the target folders do not exist yet. A second run sets HOME to a symbolic link.
The new tests on main, then on this branch:
runner.integration,docs.check,code.check,tsc -p tsconfig.pure.json,format.sh --check,version.check origin/mainandclaude plugin validate .exit 0.A trial merge with #83 (docs sentence merged, version 0.12.19) passes 260 tests, and the same Claude Code runs give the same "After" lines.
Reading map
tests/hints.test.tslines 1606-1662 add a link model forfs.statand three tests. No test is removed or weakened..claude-plugin/plugin.jsonline 3, the version.hooks/register.tsxlines 792-822:realFormOf, andlandingsandguardedHintDirsuse it.docs/hints.mdxlines 230-232.