Skip to content

[codex] Fix Windows allowedRoots bypass#40

Draft
Ahmed-Hindy wants to merge 1 commit into
Waishnav:mainfrom
Ahmed-Hindy:codex/fix-windows-allowedroots-bypass
Draft

[codex] Fix Windows allowedRoots bypass#40
Ahmed-Hindy wants to merge 1 commit into
Waishnav:mainfrom
Ahmed-Hindy:codex/fix-windows-allowedroots-bypass

Conversation

@Ahmed-Hindy

Copy link
Copy Markdown

Summary

Fixes #13.

This PR closes a Windows-specific allowedRoots bypass where a path on a different drive from the configured allowlist root could be treated as allowed.

Root cause

isPathInsideRoot() uses path.relative(resolvedRoot, resolvedPath) to decide whether a requested path is contained by an allowed root. The existing check rejected relative paths that escaped the root with .. segments:

!relationship.startsWith("..") &&
relationship !== ".." &&
!relationship.includes(`..${sep}`)

That is enough for same-drive Windows paths and POSIX paths, but it misses an important Windows behavior: when path.relative() compares paths on different drives, it can return an absolute path instead of a ..-prefixed relative path.

For example:

path.relative(
  "G:\\Projects\\Dev\\Github\\devspace",
  "C:\\Users\\Administrator",
);

// "C:\\Users\\Administrator"

Because "C:\\Users\\Administrator" does not start with .., the old predicate could incorrectly accept it as inside the allowed root.

Security impact

This undermines the filesystem allowlist boundary on Windows. A server configured with a narrow allowlist such as:

G:\Projects\Dev\Github\devspace

could still allow MCP clients to open a workspace under a different drive, such as:

C:\Users\Administrator

That matches the class of behavior reported in #13 and can allow reads/writes outside the configured approved roots.

Changes

  • Import isAbsolute from node:path.
  • Reject absolute path.relative() results inside isPathInsideRoot().
  • Add a Windows-only regression test that verifies C:\Users\Administrator is rejected when the only allowed root is on G:\....

Why this fix

A valid contained path should produce either:

  • an empty relationship, when the path is the root itself; or
  • a non-absolute relative path that does not escape through ...

So the containment check now requires the relationship to be non-absolute before accepting it:

!isAbsolute(relationship)

This preserves the existing same-drive behavior while closing the cross-drive Windows bypass.

Validation

Ran on Windows:

npx tsx src/roots.test.ts
npm run typecheck
npm test
npm run build

All passed.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c595922a-5241-4031-9cbe-f7063e7228fa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

'allowedRoots' have some problems

1 participant