diff --git a/scripts/cowork-vm-service.js b/scripts/cowork-vm-service.js index 4e6cf87..256f648 100644 --- a/scripts/cowork-vm-service.js +++ b/scripts/cowork-vm-service.js @@ -731,7 +731,7 @@ class HostBackend extends LocalBackend { async mountPath(params) { const { subpath } = params; log(`HostBackend mountPath: ${subpath}`); - const guestPath = path.join(os.homedir(), subpath || ''); + const guestPath = path.join('/', subpath || ''); return { guestPath }; } } @@ -910,7 +910,7 @@ class BwrapBackend extends LocalBackend { async mountPath(params) { const { subpath, mountName } = params; log(`BwrapBackend mountPath: ${mountName} -> ${subpath}`); - const hostPath = path.join(os.homedir(), subpath || ''); + const hostPath = path.join('/', subpath || ''); // Store for --bind on next spawn this.mountBinds.set(mountName || subpath, hostPath); return { guestPath: hostPath }; @@ -1720,7 +1720,7 @@ class KvmBackend extends BackendBase { } // No home share — return host path with a warning - const hostPath = path.join(os.homedir(), subpath || ''); + const hostPath = path.join('/', subpath || ''); log('KvmBackend: no home share, returning host path'); return { guestPath: hostPath }; } diff --git a/tests/cowork-path-translation.bats b/tests/cowork-path-translation.bats index f559e5f..5144458 100644 --- a/tests/cowork-path-translation.bats +++ b/tests/cowork-path-translation.bats @@ -823,3 +823,43 @@ assertEqual( " [[ "$status" -eq 0 ]] } + +# ============================================================================= +# mountPath — subpath is root-relative, must NOT be joined with homedir +# ============================================================================= + +# These tests replicate the mountPath() logic from HostBackend and +# BwrapBackend to verify that root-relative subpaths resolve correctly +# (fix for #373: double-nested home directory paths). + +@test "mountPath: root-relative subpath resolves to absolute path, not double-nested" { + run node -e "${NODE_PREAMBLE} +// Simulate what the caller sends: path.relative('/', '/home/user/.config/Claude') +const subpath = 'home/user/.config/Claude'; + +// Fixed logic: join with '/' (root), not os.homedir() +const guestPath = path.join('/', subpath); +assertEqual(guestPath, '/home/user/.config/Claude', + 'root-relative subpath should resolve to single absolute path'); +" + [[ "$status" -eq 0 ]] +} + +@test "mountPath: empty subpath resolves to root" { + run node -e "${NODE_PREAMBLE} +const guestPath = path.join('/', ''); +assertEqual(guestPath, '/', 'empty subpath -> root'); +" + [[ "$status" -eq 0 ]] +} + +@test "mountPath: subpath with nested directories resolves correctly" { + run node -e "${NODE_PREAMBLE} +const subpath = 'home/raycharlizard/.config/Claude/local-agent-mode-sessions/outputs'; +const guestPath = path.join('/', subpath); +assertEqual(guestPath, + '/home/raycharlizard/.config/Claude/local-agent-mode-sessions/outputs', + 'nested subpath should not double the home prefix'); +" + [[ "$status" -eq 0 ]] +}