You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
server/lib/browser-policy.ts:validateBrowserUrl and the matching path check inside electron/main.ts:validatePreviewUrl decide whether a file:// preview URL is allowed with a lexical path.relative(projectRoot, filePath) comparison. A symlink that lives inside the worktree but points to a target outside it passes the check (the link itself is in-worktree), while Chromium follows the symlink and renders the target — the same privilege gap the #357 review surfaced for the new setFiles action.
The fix in #356 (PR #357) was to run both sides of the comparison through realpath before checking. The file:// path through validateBrowserUrl / validatePreviewUrl is on the same boundary and should be hardened identically:
electron/main.ts:isPathInside (around line 121) duplicates the helper for the main-process re-check and needs the same treatment.
Tests in server/lib/__tests__/browser-policy.test.ts should cover the new symlink-escape case for file:// URLs the same way the new validateBrowserFilePath tests do.
Why it matters
A v1 Preview pane or an agent-driven controller browser open ./build/index.html resolves to file://…/build/index.html. If the project contains a symlink at build/index.html → /etc/passwd (or any host-readable path), the agent can navigate to a file outside the worktree via the OS file picker or a relative URL, and Chromium will follow the link.
This is the file-preview counterpart to the upload-side gap #356 closed, and the same P1 severity. Worth fixing as a small follow-up so the two surfaces stay consistent.
Acceptance criteria
validateBrowserUrl rejects file:// URLs whose realpath target is outside the canonicalized worktree root.
electron/main.ts:validatePreviewUrl re-check enforces the same rule.
A symlink inside the worktree pointing outside is classified as outside-project / blocked, regardless of the lexical path.
Tests cover the symlink-escape case for both the URL policy and the main-process re-check.
No regression to the existing project-relative / absolute / localhost path tests.
Summary
server/lib/browser-policy.ts:validateBrowserUrland the matching path check insideelectron/main.ts:validatePreviewUrldecide whether afile://preview URL is allowed with a lexicalpath.relative(projectRoot, filePath)comparison. A symlink that lives inside the worktree but points to a target outside it passes the check (the link itself is in-worktree), while Chromium follows the symlink and renders the target — the same privilege gap the #357 review surfaced for the newsetFilesaction.The fix in #356 (PR #357) was to run both sides of the comparison through
realpathbefore checking. Thefile://path throughvalidateBrowserUrl/validatePreviewUrlis on the same boundary and should be hardened identically:server/lib/browser-policy.ts:isPathInsideis shared withvalidateBrowserUrland would be a natural place to switch to a canonicalized comparison (with acanonicalizeForBoundaryhelper, mirroring what Browser bridge: drive native file picker so agents can upload without manual intervention #356 added forvalidateBrowserFilePath).electron/main.ts:isPathInside(around line 121) duplicates the helper for the main-process re-check and needs the same treatment.server/lib/__tests__/browser-policy.test.tsshould cover the new symlink-escape case forfile://URLs the same way the newvalidateBrowserFilePathtests do.Why it matters
A v1 Preview pane or an agent-driven
controller browser open ./build/index.htmlresolves tofile://…/build/index.html. If the project contains a symlink atbuild/index.html → /etc/passwd(or any host-readable path), the agent can navigate to a file outside the worktree via the OS file picker or a relative URL, and Chromium will follow the link.This is the file-preview counterpart to the upload-side gap #356 closed, and the same P1 severity. Worth fixing as a small follow-up so the two surfaces stay consistent.
Acceptance criteria
validateBrowserUrlrejectsfile://URLs whose realpath target is outside the canonicalized worktree root.electron/main.ts:validatePreviewUrlre-check enforces the same rule.