Skip to content

npm's .ps1 shim wins the PATH race and nothing can run it

aliases · case

bothhard-errorscriptagentfirst-partyrepro: verifiedpathext-resolutionexecution-policy-gate
Affectsnode, powershell 51, pwsh 7, cmd, windows
Fails asPSSECURITYEXCEPTION
Mechanismpathext resolution, execution policy gate
Safe fixget command

Tool detection finds “npm” but every attempt to execute it fails: cmd.exe says it can’t run the file, spawn calls error out, or execution policy blocks it. Meanwhile npm.cmd sits right next to it, working fine.

Terminal window
# npm installs THREE shims side by side: npm, npm.cmd, npm.ps1
Get-Command npm # PowerShell may resolve npm.ps1 first
# cmd.exe /c npm.ps1 → not executable via ComSpec
# Restricted policy → npm.ps1 blocked entirely

npm ships tool, tool.cmd, and tool.ps1 shims. Get-Command and PATHEXT resolution can select the .ps1, which (a) execution policy may block, (b) cmd.exe/ComSpec cannot execute, and (c) CreateProcess cannot launch directly. The extensionless file is a POSIX sh script — equally unrunnable natively.

  • Resolve explicitly in preference order .exe > .cmd, never .ps1: Resolve-CommandPath @('npm.cmd','npm.exe','npm') or Get-Command npm -CommandType Application.
  • In spawn logic, treat .ps1 as non-launchable (needs an interpreter); the referenced fix rejects it even when PATHEXT lists it.