Repository navigation
Audit the browser binaryPath gate; resolve context directories without following a link to a share - #1156
Merged
Conversation
The executable gate on a browser provider's binaryPath was a feature-spec rule in dor-browser.md, so the local audit met it only in its open sweep. It is now a FAIL IF under security-local.md -> "Spawned programs": a host spawning (or, for Playwright, loading playwright-core beside) a path the gate refused, the gate accepting a UNC, device, relative, `..`, or control-character path or another file name, or the webview sending or storing one it refuses. The path crosses from the webview realm, which also writes the saved pane params, so a same-user writer does not lower its severity. dor-browser.md keeps the drop-not-fatal behavior and the override variables and points at the new rule; the gate's rationale moves to security-local.rationale.md, with why a UNC path matters. The unc-binary-path seed now names the rule it breaks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The terminal context's Explore action and Workspace auto-naming's git lookup checked the reported path for a UNC or device spelling, then canonicalized it with realpath. realpath reaches each link's target while resolving it, so a local symlink or junction to \\host\share passed the string check and reached the share. canonicalLocalDirectory (lib/src/host/local-directory.ts) now resolves one component at a time with lstat and readlink, which never follow a link, and refuses a link whose target is a share or device path before anything follows it. git-info uses it directly; pty-core takes it as an injected resolver from the sidecar (through git-info.cjs) and VS Code's PTY host, and opens nothing without one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… plainly Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deploying mouseterm with
|
| Latest commit: |
5266b3c
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://64dd3efc.mouseterm.pages.dev |
| Branch Preview URL: | https://audit-binary-path-gate.mouseterm.pages.dev |
nedtwigg
requested a deployment
to
hosted-preview
October 17, 2026 02:17 — with
GitHub Actions
Waiting
dormouse-bot
left a comment
Collaborator
There was a problem hiding this comment.
Three comments outside the diff still cite docs/specs/dor-browser.md → "Browser Host" as the place that says what may be spawned as a browser CLI. This PR moves that rule to docs/specs/security-local.md → "Spawned programs" #4. "Browser Host" now keeps only the override variables and the drop-on-refusal rule, so a reader who follows these pointers to the gate's edges finds nothing there. The heading still exists, so the spec lint stays green:
- the header comment of
lib/src/lib/agent-browser-binary.ts("What may be spawned as a browser provider's CLI (docs/specs/dor-browser.md → "Browser Host")") - the comment above
describe('isAllowedAgentBrowserBinary'inlib/src/lib/agent-browser-binary.test.ts("so its edges are the test (docs/specs/dor-browser.md → "Browser Host")") - the comment above the predicates in
dor-lib-common/src/browser-providers.ts("What may be spawned as a browser provider's CLI (docs/specs/dor-browser.md → "Browser Host")")
Re-pointing each one at docs/specs/security-local.md → "Spawned programs" would fix it. I can push that as a commit if you'd like.
The rule moved to "Spawned programs"; "Browser Host" keeps only the override variables and the drop-on-refusal rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dormouse-bot
approved these changes
Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two local-security changes.
1. The browser
binaryPathgate is an audited ruledocs/specs/dor-browser.mdrequired thebinaryPathcheck as a feature-spec Must, so the nightly audit had no mechanical check for it. It is now FAIL IFdocs/specs/security-local.md-> "Spawned programs" #4. That rule covers the hosts' spawn sites, Playwright's in-processplaywright-coreload,dor's pinned executable, what the gate may accept, and the webview's own check before it sends or stores a path. It also says the path crosses from the webview realm, so a same-user writer is no reason to rate a break below WARNING. The webview writes a pane's saved params, which is the realm the gate fences.dor-browser.mdkeeps the override variables and "a refusedbinaryPathis dropped, never fatal", and points at the new section for what the gate accepts.security-local.rationale.md-> "Spawned programs". A UNC path lets whoever controls the share supply the binary, and on Windows reaching\\host\sharecan send the user's NTLM credentials.unc-binary-pathcanary seed now names that rule and stays at WARNING. The rule is appended, so no other rule id moved.security-local.mdword budget is ratcheted to 5000.2. A context directory is resolved without following a link to a share
canonicalDirectoryinlib/src/host/git-info.tsandopenDirectoryinstandalone/sidecar/pty-core.jsrefused a UNC or device path by its text, then calledrealpath, andpty-corecalledstatbefore that. Both follow links. A local symlink or junction to\\server\sharepassed the text check, and resolving it already reached the share before any check of the result.canonicalLocalDirectoryin the newlib/src/host/local-directory.tsresolves one component at a time withlstatandreadlink, which never follow a link. It refuses a link whose target is a share or device path before following it, caps at 40 links, and requires the result to be a directory. Both call sites use it:git-info.tsdirectly.pty-corethrough a new injectedcanonicalDirectoryoption, whose default opens nothing. The sidecar'smain.jspasses it fromgit-info.cjs, and VS Code'spty-host.jsbundles it.The "Terminal context directory actions" FAIL IF now names "a link whose target is one" as well.
What it does not cover:
Tests
Each new test went red with the line it pins reverted:
lib/src/host/local-directory.test.ts://target, a\\host\sharetarget with a real directory of that name, a link mid-path, and a link to a linklib/src/host/git-info.test.ts: never follows a link to a share.standalone/sidecar/helper-terminal.test.js:openDirectorytouches the path only through the resolver.pty-corethe shared resolver:standalone/sidecar/main-wiring.test.jsandvscode-ext/test/pty-host-wiring.test.ts.Commands run, all passing: spec, markdown, public-docs, loopback, and outbound lints;
scripts/security-audit*.test.mjs(154/154); libvitest run src/hostandtsc -b; standalonetsc --noEmitand sidecarpnpm teston Node 24.18; vscode-extvitest run.This changes
.github/audit/canaries/, so it needs a maintainer merge.🤖 Generated with Claude Code