diff --git a/docs/specs/security.md b/docs/specs/security.md index 76ffbf2a7..e89032295 100644 --- a/docs/specs/security.md +++ b/docs/specs/security.md @@ -44,6 +44,7 @@ Source of truth: root scripts in `package.json`; native jobs in `.github/workflo - **A process running as you.** `dor`, its socket, and every file mode bound other local accounts, never a program already running under your own account; an agent holding `dor` has exactly the power of the person at the keyboard, and the Tool trust prompt is no boundary against it ([The dor control socket](./security-local.md#the-dor-control-socket)). - **The Windows `dor` pipe carries no ACL of ours.** A named pipe has no directory to harden, so an unguessable name and the token handshake are the whole of it ([The dor control socket](./security-local.md#the-dor-control-socket)). +- **Another Windows account can take the VS Code peer-link pipe's name first.** Every window must bind the same name, so it is derived, not random, and Windows lists every pipe to every account; whoever creates it first keeps remote control and peer surfaces down, though the token handshake serves them nothing ([Persisted state](./security-local.md#persisted-state)). - **A local HTML or SVG document you open, or confirm from a document link, can send its contents off the machine.** The file viewer's content policy confines what the page loads, not where its scripts navigate ([Local-file viewer](./security-local.md#local-file-viewer)). - **A mermaid sanitizer bypass in a Markdown document you open.** Its diagrams reach the editor page through mermaid's strict sanitizer, not the editor's allowlist, so a bypass would run script holding the editor's save, image, and document-open routes; an open of a page that runs its own scripts still waits on Dormouse's own dialog ([Local-file viewer](./security-local.md#local-file-viewer), [Terminal output](./security-local.md#terminal-output)). - **A Tool trust grant on an upstream URL trusts the URL a checkout claims.** Any directory whose own `.git/config` claims an already-granted upstream shares that grant; a folder-only grant is not shared ([Dor Tool configuration](./security-local.md#dor-tool-configuration)). diff --git a/docs/specs/vscode.md b/docs/specs/vscode.md index 5d2b24582..1d8e462f2 100644 --- a/docs/specs/vscode.md +++ b/docs/specs/vscode.md @@ -144,7 +144,7 @@ Source of truth: `VsCodeBurrowStateStore` in `vscode-ext/src/burrow-store.ts`, ` **Trust.** The socket path is derived, not secret, so two layers stand between it and this installation's terminals. -*The directory.* On unix every bind and connect is held to `peerDirIsSafe()`, the predicate the `dor` control socket uses (`docs/specs/security-local.md` → "The dor control socket"). A loose directory we own is tightened; anything else is somebody else's and **the peer link stands down for good**, releasing the callers waiting on the contention. Windows named pipes carry their own ACL and skip this layer. +*The directory.* On unix every bind and connect is held to `peerDirIsSafe()`, the predicate the `dor` control socket uses (`docs/specs/security-local.md` → "The dor control socket"). A loose directory we own is tightened; anything else is somebody else's and **the peer link stands down for good**, releasing the callers waiting on the contention. Windows pipes have no directory and skip this layer (`docs/specs/security.md` → "What is not defended"). *The handshake.* The shared secret is a mode-0600 `burrow.peer-token` in `globalStorageUri`, **created once with an exclusive `wx` write rather than a rename** so two windows starting together agree on one token. **Treat an empty read as *not yet written*, never as the token**, waiting it out with a bounded retry (rationale); **exhausting that wait latches the same permanent stand-down** as an unsafe directory. The token **never crosses the socket**; three frames prove mutual knowledge of it: diff --git a/scripts/spec-word-budgets.json b/scripts/spec-word-budgets.json index f38d39214..7feb9dbcb 100644 --- a/scripts/spec-word-budgets.json +++ b/scripts/spec-word-budgets.json @@ -30,7 +30,7 @@ "docs/specs/security-local.md": 5900, "docs/specs/security-remote.md": 7100, "docs/specs/security-supply-chain.md": 1650, - "docs/specs/security.md": 2600, + "docs/specs/security.md": 2650, "docs/specs/shortcuts.md": 1150, "docs/specs/standalone.md": 6450, "docs/specs/terminal-context.md": 950, diff --git a/vscode-ext/src/peer-link.ts b/vscode-ext/src/peer-link.ts index 16c06bbef..62fb7ec79 100644 --- a/vscode-ext/src/peer-link.ts +++ b/vscode-ext/src/peer-link.ts @@ -145,8 +145,9 @@ function peerDirPath(): string { * possibly on purpose, and no amount of retrying makes it ours — so the caller * stands the peer link down for good rather than spinning against it. * - * Windows named pipes are not filesystem objects and carry their own ACL, so - * there is nothing here for them to check. + * Windows named pipes are not filesystem objects, so there is no directory + * here to check; the squat that leaves open is recorded in + * `docs/specs/security.md` → "What is not defended". * * The same predicate is duplicated as `ensureControlDir()` in * standalone/sidecar/dor-control-server.js (sync fs, returns the directory