fix(security): use lstat in claude session discovery to skip symlinks (#153 — gap 2)#157
Conversation
…getagentseal#153) `findDesktopProjectDirs` and `discoverSessions` in `src/providers/claude.ts` walked the session tree with `stat`, which transparently follows symbolic links. A symlink inside `~/.claude/projects/` (or in the macOS / Linux / Windows desktop sessions tree) would let the walk descend anywhere on the filesystem the calling user can read. Switch to `lstat` and explicitly skip symbolic links. Regular directories behave identically; only symlinked entries are now refused. Adds `tests/providers/claude-symlink.test.ts` covering both branches: - a symlinked entry inside the projects dir is dropped from `discoverSessions` output - a regular project directory next to it is still discovered Addresses gap getagentseal#2 from getagentseal#153 ("Walk functions (providers/claude.ts) don't check for symlinks. Use lstat, skip symbolic links."). Gap getagentseal#1 (ANSI sanitization) is in a separate PR. Co-Authored-By: Ora Studio <noreply@oratelecom.net>
|
Hi, The new symlink test creates a directory symlink without Windows-safe options or error handling, which can fail on win32 (often EPERM/EACCES) and break CI/dev runs on Windows. Severity: action required | Category: reliability How to fix: Make symlink creation Windows-safe Agent prompt to fix - you can give this to your LLM of choice:
We noticed a couple of other issues in this PR as well - happy to share if helpful. Found by Qodo. Free code review for open-source maintainers. |
- Use 'junction' symlink type on win32 for directory symlinks - Skip test gracefully on EPERM/EACCES so envs without symlink permission don't fail CI - Preserves the original guarantee: real shady-link symlink is created and asserted to be skipped on platforms that allow it Addresses Qodo bot feedback on getagentseal#157.
|
Thanks for the catch. Pushed
Full suite: 357 / 357. |
|
Closing this — appreciate the effort, but the threat model doesn't justify the change. codeburn only reads files (no execution, no remote exfil), so symlink following is a non-risk in practice. The PR also only covers one provider while five others have the same pattern. If we decide to add symlink protection later, we'll do it across all providers in one pass. Thanks for the contribution though. |
Summary
Addresses gap #2 of #153 ("Walk functions (providers/claude.ts) don't check for symlinks. Use lstat, skip symbolic links.").
findDesktopProjectDirsanddiscoverSessionsinsrc/providers/claude.tswalk the session tree withstat, which transparently follows symbolic links. A symlink under~/.claude/projects/(or anywhere within the macOS / Linux / Windows Claude Desktop sessions trees) lets the walk descend to any path the calling user can read — outside the intended sandbox.Fix
Switch the imports from
stat→lstatand explicitly skip symbolic links:Regular directories behave identically; only symlinks are refused. Three call sites in
claude.ts:findDesktopProjectDirsprojects/*walk infindDesktopProjectDirs~/.claude/projects/walk indiscoverSessionsVerification
tests/providers/claude-symlink.test.tsfails on the unfixed code (verified by stashing the fix and re-running —'shady-link'was discovered)npx tsc --noEmitclean{}-init maps insrc/parser.tsorsrc/providers/(semgrep guard)Out of scope
Gap #1 of #153 (ANSI sanitization of displayed strings) is the companion PR.
The same
stat-vs-lstatpattern exists in other providers (pi,codex,copilot). Per the issue text the symptom was reported inproviders/claude.ts, and a single-provider PR is easier to review than a sweep. Happy to follow up across the other providers in a separate PR if you'd like.Files changed
src/providers/claude.tsstat→lstat; explicit symlink skip at 3 call sitestests/providers/claude-symlink.test.tsVibe Coded by Ousama Ben Younes
Developed With Ora Studio (Claude Code)