Skip to content

fix(core): getHomeDir() can resolve to drive root, causing full-disk scan on Windows #433

Description

@christso

Summary

A user reported this crash running npx allagents plugin install cargowise@wtg-ai-prompts --scope user:

Installing plugin "cargowise@wtg-ai-prompts"...

Error: EPERM: operation not permitted, scandir 'C:\$WinREAgent\Scratch\Mount\Windows\System32\LogFiles\WMI\RtBackup'

$WinREAgent\... is a SYSTEM/TrustedInstaller-only folder at the root of the C: drive. The only way a Node process can reach a path 7 levels deep under it is by recursively walking C:\ itself.

Root cause

getHomeDir() in src/constants.ts:

export function getHomeDir(): string {
  return process.env.HOME || process.env.USERPROFILE || '~';
}

This is used as the workspace root for every --scope user operation (src/core/sync.ts, src/core/marketplace.ts, src/core/plugin.ts, etc. — 15 call sites). It prioritizes process.env.HOME over USERPROFILE. HOME isn't a native Windows env var, but Git Bash/MSYS-based shells set it — and MSYS auto-translates a misconfigured HOME=/c into the literal Windows path C:\ when spawning a native process like node.exe.

Reproduced directly:

$ HOME=/c node -e "console.log(process.env.HOME)"
C:\

If a user's shell has HOME set to /c instead of /c/Users/<name> (broken .bashrc//etc/profile, corporate provisioning script, leftover Cygwin config, etc.), allagents treats the entire C: drive as "home" for user-scope sync, and whichever downstream step walks the workspace tree (skill/plugin discovery, purge, or a native CLI it shells out to) ends up scanning the whole drive and hits the permission-locked $WinREAgent folder.

Why this is avoidable

Node's built-in os.homedir() does not consult process.env.HOME on Windows at all — it uses USERPROFILE / the native GetUserProfileDirectory API, so it's immune to this exact failure mode:

$ HOME=/c node -e "console.log(require('os').homedir())"
C:\Users\Christopher.Tso

vercel-labs/skills (a comparable multi-agent skills CLI) uses os.homedir() universally for the home directory and layers xdg-basedir + explicit override env vars (CODEX_HOME, CLAUDE_CONFIG_DIR, etc.) on top for config paths — never trusting HOME as the primary source of truth.

Proposed fix

Replace getHomeDir()'s implementation with os.homedir() (single call site fix, no changes needed at the 15 usages).

Reproduction (mechanism only)

HOME=/c node -e "console.log('env.HOME=', process.env.HOME); console.log('os.homedir=', require('os').homedir())"
# env.HOME= C:\
# os.homedir= C:\Users\<real-user>   <- unaffected

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions