v0.16.5
Three attach-triggered vulnerabilities, all live in 0.16.4 and all reachable from a hostile clone. If you use plumb on repositories you did not write, upgrade.
Full detail for every item is in CHANGELOG.md — this is the readable summary.
Security
All three are triggered by attaching a session to a repository. No tool call is needed, and nothing in the repository looks unusual — the payload is a committed symlink or a committed file.
- A cloned repository could delete directories anywhere you can write.
transaction_applykeeps a write-ahead log under<workspace>/.plumb/tx-log/, andtxlog.Scanwalks it on every attach and re-pin to roll back orphans. That path is an ordinary directory inside the workspace, so a repository can ship it — as a symlink. Scanning followed it out of the workspace and cleaned up what it found there. No manifest was required. - A cloned repository could write a file anywhere you can write, with mode bits of its choosing. Same scan, via a committed orphan manifest: the rollback wrote the manifest's recorded content to the manifest's recorded path, neither of which was confined to the workspace.
- A committed symlink plus
..defeated the workspace boundary outright. Every boundary check ranfilepath.Absfirst, which cancelssub/..lexically before any link is resolved; the kernel does the opposite, followingsuband then applying..to wherever that landed. Whensubis a symlink out of the workspace the two readings name different files, and the syscall received the same uncleaned text the check had approved. Measured against the real tools:write_filewrote outside every allowed root,read_filedisclosed the target,find_fileslisted it. One committedsub -> /made the whole filesystem addressable as in-workspace. Such a path is now refused rather than cleaned — cleaning it would keep every call working while silently retargeting it to a different file than the caller named. - Four more project-config fields that could soften a global safety setting are now covered by the trust gate.
Changed
- Kotlin moves to JetBrains'
kotlin-lspand is promoted out of experimental. Note the macOS quarantine step indocs/adding-an-lsp.md— macOS silently deletes the unsigned server binary on first run unless it is cleared. [collab]'s channel switches are gated onplumb trustinstead of being forced global-only. 0.16.4 closed a real hole by making them global-only, but that also removed per-workspace chat settings entirely. Trust separates the two questions: settings can vary per workspace, while the user — not the repository — decides whether this repository's settings are honoured.- Per-root language-server state directories are a table rather than a special case.
Fixed
- Two live sessions can no longer share a name, so a mailbox address always reaches the session it names. A name is an address: notes are stored and notified by the name string, so a duplicate silently misdelivered.
- A tool added by a daemon rebuild is no longer invisible to already-connected clients. The tool list is fetched once at connect, and
plumb serveis a reconnecting proxy — so from the client's side the server never goes away and never re-lists. The proxy now emitsnotifications/tools/list_changedafter a reconnect. This is the case plumb's own dev loop hits constantly: rebuild the daemon under a live agent session and the new tool was unusable until the client restarted.
Install: brew install plumbkit/plumb/plumb, or grab a binary below (macOS and Linux, arm64 and amd64). Existing Homebrew users: brew update && brew upgrade plumb.