Skip to content

fix: correct workspace root containment check for root paths - #1111

Open
MacLeod92 wants to merge 2 commits into
siteboon:mainfrom
MacLeod92:fix/root-containment-double-separator
Open

fix: correct workspace root containment check for root paths#1111
MacLeod92 wants to merge 2 commits into
siteboon:mainfrom
MacLeod92:fix/root-containment-double-separator

Conversation

@MacLeod92

@MacLeod92 MacLeod92 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Problem

The function validateWorkspacePath checks two conditions with a string comparison. It tests whether a path starts with the workspace root plus one separator. This check fails when the workspace root itself resolves to a filesystem root, such as / on Unix or C:\ on Windows.

A filesystem root already ends in a separator. The check appends a second separator before the comparison. This produces a string like // or C:\\, which no normal absolute path starts with. As a result, every requested path gets rejected, even paths that are correct and safe.

Cause

The environment variable WORKSPACES_ROOT sets the workspace root. This variable does not pass through FORBIDDEN_WORKSPACE_PATHS. An operator can set WORKSPACES_ROOT to a drive root on Windows, since the forbidden list blocks specific Windows paths but not the drive root itself. In this case, the broken check runs on every request, with no earlier guard to catch it.

Fix

This PR adds a function named isPathWithinRoot. The function uses path.relative in place of string-prefix matching. It compares the relative path between the root and the target. It reports containment as true when the relative path is empty, or when the relative path does not start with .. and is not itself absolute.

This PR also removes the two duplicate if blocks that ran the broken check. Both call sites, the main containment check and the symlink-target check, now call the shared function.

Testing

Single commit, server/shared/utils.ts only (+14/-8). This fix has been running in a private build since 2026-07-01 without issues. I confirmed the original check rejects valid paths when the workspace root resolves to /. I confirmed the new function accepts these same paths. I ran the existing test suite. I found no regressions in normal, non-root workspace configurations.

Summary by CodeRabbit

  • Bug Fixes
    • Improved workspace path validation to reliably recognize paths contained within the permitted workspace.
    • Prevented edge cases where similarly named directories or symbolic links could be incorrectly treated as being inside the workspace.
    • Enhanced protection against accessing files outside the intended workspace boundaries.
    • Improved handling of paths that exactly match the workspace root or are nested within it.

validateWorkspacePath checked containment via
path.startsWith(`${root}${path.sep}`), which appends a path separator
unconditionally. When WORKSPACES_ROOT resolves to an actual filesystem
root ("/" on Unix, "C:\\" on Windows), the root already ends in a
separator, so the check effectively looked for a double separator that
no real path has — rejecting every path except the root itself, with
"Workspace path must be within the allowed workspace root: /" even for
genuinely contained paths. The same bug existed in the adjacent
symlink-target check.

Replaced both with a shared isPathWithinRoot helper based on
path.relative, which handles root paths, drive letters, and trailing
separators correctly without manual separator bookkeeping.
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9bf17abe-d7f8-4bc8-9645-0fab14d92fce

📥 Commits

Reviewing files that changed from the base of the PR and between 1592828 and ce509d3.

📒 Files selected for processing (1)
  • server/shared/utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/shared/utils.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Changes

Path containment validation

Layer / File(s) Summary
Containment helper and validation integrations
server/shared/utils.ts
Adds isPathWithinRoot for root and descendant paths. The helper rejects parent traversal and absolute paths. Workspace-root and symlink-target validation use the helper instead of string-prefix checks.

Poem

I’m a rabbit checking paths tonight,
Roots stay safe beneath moonlight.
Symlinks follow trails kept clear,
Escapes cannot hop near.
Prefix tricks vanish from sight.

Merge Risk: ⚪ Minimal · up to ce509

The change corrects workspace containment handling for filesystem-root paths and centralizes the check without any actionable merge-blocking risk remaining.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main fix to workspace root containment checks for filesystem root paths.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/shared/utils.ts`:
- Around line 211-214: Update isPathWithinRoot so descendant paths whose names
begin with “..” remain valid; reject only a relative path equal to “..” or
starting with “..” followed by path.sep, while preserving the existing
absolute-path and root-path handling.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e36694e5-ec7e-446e-89dc-15f284e1109e

📥 Commits

Reviewing files that changed from the base of the PR and between f0dca2d and 206309f.

📒 Files selected for processing (1)
  • server/shared/utils.ts

Comment thread server/shared/utils.ts
…versal

isPathWithinRoot rejected any relative path that starts with the two
characters "..", including a real directory name like "..cache" that
is not parent traversal at all. path.relative('/workspaces',
'/workspaces/..cache') returns "..cache", and the old check treated
that string prefix as an escape attempt, rejecting a path that never
leaves the root.

Addresses a review comment from CodeRabbit on this PR. The fix now
checks for an exact ".." segment or a ".." followed by a path
separator, so only genuine parent traversal is rejected. A descendant
name that merely begins with ".." is now treated as contained, as it
should be.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants