Fix: Path Traversal in File Tools#342
Conversation
Contributor License AgreementAll contributors are covered by a CLA. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 33e1057. Configure here.
| const realRel = relative(root, realTarget); | ||
| if (realRel.startsWith("..") || isAbsolute(realRel)) { | ||
| throw new Error(`Path "${filePath}" points outside the workspace via a symlink and was rejected.`); | ||
| } |
There was a problem hiding this comment.
Symlink bypass on new paths
High Severity
When the target path does not exist yet, safeRealpath falls back to resolve, which does not follow symlinks in existing parent segments. A path that stays lexically under the workspace can still pass both checks if a directory component is a symlink outside the workspace, so writeFile can create files on the host.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 33e1057. Configure here.
| const rel = relative(root, full); | ||
| if (rel.startsWith("..") || isAbsolute(rel)) { | ||
| throw new Error(`Path "${filePath}" resolves outside the workspace and was rejected.`); | ||
| } |
There was a problem hiding this comment.
Cwd symlink false rejection
Medium Severity
The workspace root is taken from safeRealpath(cwd) while the candidate path uses resolve(cwd, filePath). path.relative compares string paths and ignores symlinks, so when the agent’s cwd is a symlink into the workspace, valid relative paths can look like ../… and be rejected even though they refer to files inside the workspace.
Reviewed by Cursor Bugbot for commit 33e1057. Configure here.
|
|
||
| const rel = relative(root, full); | ||
| if (rel.startsWith("..") || isAbsolute(rel)) { | ||
| throw new Error(`Path "${filePath}" resolves outside the workspace and was rejected.`); |
There was a problem hiding this comment.
Dot-dot filename false reject
Low Severity
Escape detection uses rel.startsWith(".."), which also matches legitimate relative paths whose first segment is a filename starting with two dots (for example ..foo), so those in-workspace files are rejected incorrectly.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 33e1057. Configure here.


Summary
Add assertInsideWorkspace (realpath + relative() prefix check, covering lexical ../ traversal and symlink escapes) and call it from resolvePath so readFile, writeFile, and editFile reject any path resolving outside the workspace, mirroring the repo's existing assertInsideSchedulesDir guard. Throws on escape so tools return a clean failure instead of touching the host.
Finding
Path Traversal in File Tools
Generated by Superagent from the proposed patch for this finding.
Note
Low Risk
Security-hardening change that only blocks invalid paths; legitimate in-workspace file operations are unchanged.
Overview
Closes a path traversal hole in agent file tools by validating every user-supplied path before read/write/edit.
Adds
assertInsideWorkspace, which canonicalizes the workspace root and target withrealpathSync(viasafeRealpathwhen resolution fails), then usesrelative()to reject paths that escape lexically (../) or via symlinks. It is invoked fromresolvePath, soreadFile,writeFile, andeditFileall fail with a clear error instead of touching files outside the workspace.Reviewed by Cursor Bugbot for commit 33e1057. Configure here.