Important
v5.0.0 — Security hardening + asar v1.569.0 compatibility. Closes 9 issues across 10 PRs from 6 contributors.
Claude Cowork Linux — v5.0.0
v4.3.1 → v5.0.0 · Security hardening · Current Desktop compatibility · 6 contributorsClaude Cowork Linux runs between two surfaces that move independently: Anthropic’s apps on one side, the Linux substrate on the other. v5.0.0 addresses both. Five security layers that were either missing or too permissive. Five compatibility gaps that were silently blocking current Desktop builds. None of this was glamorous work — but it’s the kind of work that makes everything else possible.
▶ TL;DR — what changed and why it matters
| Area | What was wrong | What’s fixed |
|---|---|---|
| Mount paths | No traversal validation on symlink creation | validateMountName() + validateRelativePathWithinHome() enforced at 3 points |
| Env vars | additionalEnv forwarded anything from the renderer |
Explicit allowlist + CLAUDE_* / ANTHROPIC_* prefix allowlist only |
| Session files | No integrity checking on disk | SHA-256 checksum stamped on write, verified on read |
| Disclaimer binary | Writable shell script on disk | Inert read-only stub; intercept happens in-process |
| Linux platform | getHostPlatform() threw on linux-x64 |
Patched; Linux is now a first-class platform |
| SDK install | Stub returning { success: true } |
Real curl + zstd download from downloads.claude.ai |
| Spawn args | VM paths not rewritten in child process args | translateVmPathsInString() handles paths + env values |
| OAuth | .desktop handler declared but never registered |
xdg-mime default set in both install.sh and launch.sh |
🔒 Security hardening
These five changes close concrete attack surface. They’re not theoretical hardening — each addresses a specific way the process boundary could be abused.
1 — Mount path validation
- createMountSymlinks
-
Mount names and relative paths from the asar are now validated before any symlink is created.
validateMountName()rejects traversal attempts outright.validateRelativePathWithinHome()ensures relative paths resolve strictly within the user’s home directory. Both checks are enforced at three points in the mount creation pipeline — not just at the entry gate.The existing root-relative path heuristic was also tightened: the comparison now uses
startsWith(homedir + '/')instead ofstartsWith(homedir), closing a prefix collision that could affect adjacent usernames on shared systems.
2 — Environment variable allowlist
- filterEnv → env_filter.js
-
Environment filtering has been extracted into a dedicated module and the rules are now explicit rather than permissive-by-default.
additionalEnvfrom the renderer is filtered through two gates: an explicitADDITIONAL_ENV_ALLOWLISTset, and a prefix allowlist coveringCLAUDE_*andANTHROPIC_*variables. Everything else is rejected.The base process environment (
process.env) continues through the existingENV_ALLOWLISTpath unchanged.
3 — Session metadata integrity
- computeMetadataChecksum / verifyMetadataChecksum
-
Session JSON files now carry a SHA-256 checksum, stamped on every write and verified on every read. On-disk modification between app launches is detected rather than silently trusted.
findSessionMetadataPathnow also rejects session IDs containing path separators, closing a related injection vector.
4 — Disclaimer wrapper hardening
- frame-fix-wrapper.js
-
The disclaimer binary — previously a writable shell script on disk — is no longer executable in any meaningful sense. It exists on disk as an inert stub (read-only, exits 127). The asar’s
execFile/spawncalls are intercepted in-process before any file is touched, and commands through the intercept must originate from system directories. The stub on disk is never reached.
5 — Security comment cleanup
All SECURITY: labels, tampering descriptions, and mechanism explanations removed from production code and log messages across 12 files. Security properties shouldn’t be documented in the attack surface they’re protecting.
🔗 Compatibility
Five gaps that were silently preventing current Desktop builds from working on Linux.
linux-x64is a supported platform now.
6 — getHostPlatform() patch
- enable-cowork.py → getHostPlatform()
-
The original implementation handled
darwinandwin32and threwUnsupported platform: linux-x64on session init. It is patched. Linux is no longer an afterthought in the platform switch.
Closes #97, #80, #76, #70 · based on @michael-greider’s #98
7 — Real installSdk()
- vm.installSdk()
-
The stub that returned
{ success: true }without doing anything is replaced with an implementation that actually installs the SDK. Downloads the correct Linux binary fromdownloads.claude.ai, validates the install path stays within~/.config/Claude/, and usesexecFileSync('curl')andexecFileSync('zstd')separately — no shell interpretation.
Closes #79 · based on @michael-greider’s #98
8 — VM path translation in spawn args
- translateVmPathsInString()
-
Rewrites
/sessions/<name>/mnt/<key>/...paths embedded inspawn()args and env var values. Stops at shell metacharacters. Refuses paths containing/..to keep mount boundaries intact.
Closes #88 · based on @F1nny’s #90
9 — Guest request methods for bridge classification
- setGuestRequestCallback / sendGuestResponse
-
Added to the VM API. Required by the asar’s
cliPluginBridgeinitializer to classify CLI plugins without crashing on init.
10 — OAuth protocol handler registration
- .desktop → xdg-mime
-
The
.desktopfile declaredx-scheme-handler/claudebut the OS was never instructed to use it. OAuth callbacks hit a dead end.xdg-mimedefault registration now runs in bothinstall.shandlaunch.sh.
📄 Also in this release
Nested mount keys — createMountSymlinks now creates parent directories for nested mount keys like .claude/skills. Previously these silently failed with ENOENT and offered no indication of why.
Additional merged PRs:
| PR | Author | Change |
|---|---|---|
| #99 | @Smiie-2 | npm install -g --prefix fix for Debian/Ubuntu |
| #94 | @pankaj4u4m | Electron binary detection in ~/.local/bin and AppImage |
✓ Issues closed
| # | Title |
|---|---|
| #97 | Unsupported platform: linux-x64 |
| #93 | OAuth signin doesn’t work |
| #88 | VM path translation in spawn args |
| #81 | Cowork project creation fails (macOS-only check) |
| #80 | No path to Claude code executable |
| #79 | OpenSUSE/nvm: installSdk stub |
| #77 | Unable to sign in |
| #76 | Code tab won’t work |
| #70 | Two startup crashes on Fedora |
☐ Remaining open
| # | Title | Status |
|---|---|---|
| #85 | Release on Flathub | Feature request |
| #64 | Tray icon missing | Compositor issue |
| #28 | Global shortcuts on Wayland | Electron upstream |
⇓ Upgrade
# From git
git pull && ./install.sh
# From AUR
yay -Syu claude-cowork-linux
# Fresh install
curl -fsSL https://raw.githubusercontent.com/johnzfitch/claude-cowork-linux/master/install.sh -o install.sh
chmod +x install.sh && ./install.sh👏 Contributors
6 contributors · 10 PRs · 9 issues closed
Thank you to everyone who opened PRs, filed detailed bug reports, and tested on their distributions. This release closed a long tail of bugs that have been open since Linux support launched — that’s entirely because of the reproduction steps and patches you provided.
| Contributor | Work |
|---|---|
| @wlcarden | Guest request bridge methods (#72) |
| @cesasol | Security hardening contributions |
| @michael-greider | getHostPlatform() patch + real installSdk() (#98) |
| @F1nny | VM path translation (#90), nested mount key fix |
| @Smiie-2 | npm prefix fix for Debian/Ubuntu (#99) |
| @pankaj4u4m | Electron binary detection (#94) |