Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: opt-in CODEGRAPH_ALLOW_SYMLINK_ESCAPE for symlink-farm roots - #3

Merged
JaimeJunr merged 1 commit into
mainfrom
feat/symlink-escape-optin
Jun 22, 2026
Merged

JaimeJunr merged 1 commit into
mainfrom
feat/symlink-escape-optin

Conversation

@JaimeJunr

Copy link
Copy Markdown
Owner

Problema

validatePathWithinRoot (colbymchenry#527) rejeita symlinks in-repo cujo alvo real escapa do root do projeto. Isso quebra workspaces consolidados multi-repo/worktree feitos de symlinks (ex.: um dir pit linkando pra repos irmãos): toda leitura é bloqueada e nada indexa (0 nós).

Solução

Flag opt-in CODEGRAPH_ALLOW_SYMLINK_ESCAPE=1 que afrouxa apenas a camada de symlink-realpath. O guard lexical ../ continua ativo. Comportamento default (flag off) inalterado — colbymchenry#527 segue fechado pra repos não confiáveis.

Testes

🤖 Generated with Claude Code

validatePathWithinRoot rejects in-repo symlinks whose real target escapes
the project root (colbymchenry#527). That blocks consolidated multi-repo/worktree
workspaces built from symlinks (e.g. a 'pit' dir linking out to sibling
repos) — every read is denied and nothing indexes.

Add an opt-in env flag that relaxes ONLY the symlink-realpath layer; the
lexical '../' traversal guard still applies. Default behavior (flag unset)
is unchanged, so colbymchenry#527 stays closed for untrusted repos.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Copilot AI review requested due to automatic review settings June 22, 2026 00:11
@JaimeJunr
JaimeJunr merged commit b5201ed into main Jun 22, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an explicit opt-in escape hatch to validatePathWithinRoot so that symlink-farm style workspaces (where in-repo symlinks intentionally point to out-of-tree checkouts) can be indexed without being blocked by the symlink-realpath containment guard introduced for colbymchenry#527.

Changes:

  • Add CODEGRAPH_ALLOW_SYMLINK_ESCAPE behavior to bypass the realpath-based “symlink escape” rejection while keeping the lexical ../ traversal guard intact.
  • Add new security tests covering the opt-in behavior for file and directory symlink escapes and confirming lexical traversal remains blocked.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/utils.ts Adds an env-flag-controlled bypass for the symlink-realpath containment check in validatePathWithinRoot.
tests/security.test.ts Adds test cases validating the new opt-in symlink escape behavior and ensuring ../ traversal is still rejected.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/utils.ts
Comment on lines 116 to +119
const realRoot = fs.realpathSync(normalizedRoot);
const realResolved = fs.realpathSync(resolved);
return isWithinDir(realResolved, realRoot) ? realResolved : null;
if (isWithinDir(realResolved, realRoot)) return realResolved;
return process.env.CODEGRAPH_ALLOW_SYMLINK_ESCAPE ? realResolved : null;
Comment on lines +258 to +277
describe('with CODEGRAPH_ALLOW_SYMLINK_ESCAPE opt-in', () => {
afterEach(() => { delete process.env.CODEGRAPH_ALLOW_SYMLINK_ESCAPE; });

it('allows an in-repo symlink to an out-of-root FILE when opted in', () => {
if (!link(path.join(root, 'escape'), path.join(outside, 'pkg', 'secret.txt'))) return;
process.env.CODEGRAPH_ALLOW_SYMLINK_ESCAPE = '1';
expect(validatePathWithinRoot(root, 'escape')).not.toBeNull();
});

it('allows escape through an out-of-root DIR symlink when opted in', () => {
if (!link(path.join(root, 'escapedir'), path.join(outside, 'pkg'))) return;
process.env.CODEGRAPH_ALLOW_SYMLINK_ESCAPE = '1';
expect(validatePathWithinRoot(root, 'escapedir/secret.txt')).not.toBeNull();
});

it('still rejects lexical ../ traversal even when opted in', () => {
process.env.CODEGRAPH_ALLOW_SYMLINK_ESCAPE = '1';
expect(validatePathWithinRoot(root, `../${path.basename(outside)}/pkg/secret.txt`)).toBeNull();
});
});
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.

2 participants