{"record":{"id":"5cd3c5f518c90aa9","repo":"JuliusBrussee/caveman","slug":"cannot-safely-launch-windows-command-shim-comma","errorCode":null,"errorMessage":"cannot safely launch Windows command shim: ${command}","messagePattern":"cannot safely launch Windows command shim: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/portable-command.ts","lineNumber":25,"sourceCode":"  for (const line of source.split(/\\r?\\n/)) {\n    if (!/(?:\\bnode(?:\\.exe)?\\b|_prog)/i.test(line) || !/%\\*/.test(line)) continue;\n    const match = line.match(/\"%(?:dp0%|~dp0)\\\\([^\"\\r\\n]+\\.(?:cjs|mjs|js))\"\\s+%\\*/i);\n    if (match) return match[1]!;\n  }\n  return null;\n}\n\nexport function portableInvocation(\n  command: string,\n  args: readonly string[],\n  platform: NodeJS.Platform = process.platform,\n): PortableInvocation {\n  if (platform !== \"win32\" || !/\\.(?:cmd|bat)$/i.test(command)) {\n    return { command, args: [...args] };\n  }\n  const stat = statSync(command);\n  if (!stat.isFile() || stat.size > 256 * 1024) {\n    throw new Error(`cannot safely launch Windows command shim: ${command}`);\n  }\n  const relativeScript = parseWindowsNodeShim(readFileSync(command, \"utf8\"));\n  if (!relativeScript) {\n    throw new Error(`cannot safely launch non-Node Windows command shim: ${command}; install a native .exe`);\n  }\n  const script = resolve(dirname(command), ...relativeScript.split(/[\\\\/]+/));\n  if (!statSync(script).isFile()) {\n    throw new Error(`Windows command shim target is missing: ${script}`);\n  }\n  return { command: process.execPath, args: [script, ...args] };\n}\n","sourceCodeStart":7,"sourceCodeEnd":37,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/cli/src/portable-command.ts#L7-L37","documentation":"On win32, when caveman must spawn a `.cmd`/`.bat` shim it refuses to use the shell file directly (CVE-2024-27980-style command-injection risk in cmd shims). It first stats the shim; if the path is not a regular file or exceeds 256 KiB it throws this error, because parsing an oversized or non-file shim is neither safe nor useful. This is the size/existence gate before the shim-content parse.","triggerScenarios":"portableInvocation(command, args) on Windows where command matches /\\.(cmd|bat)$/i and statSync shows a directory, a symlink/pipe rather than a plain file, or a shim file larger than 256 KiB.","commonSituations":"Passing a directory that merely ends in .cmd, a broken npm/pnpm install producing a bloated or malformed shim, PATH resolution landing on a stub .cmd from an unpacked archive, or antivirus replacing the shim with something huge.","solutions":["Check the path: run `dir <command>` and confirm it is a regular file well under 256 KiB (npm shims are a few hundred bytes).","Reinstall the package that owns the shim (npm reinstall / pnpm install) to regenerate a clean, small shim.","Point caveman at the underlying Node script or a native .exe instead of the .cmd shim.","If a wrapper script genuinely must be large, invoke node directly on your script and skip the .cmd indirection."],"exampleFix":"# before\nportableInvocation(\"C:\\tools\\mytool.cmd\", args)  # mytool.cmd is 1 MiB\n# after: small Node shim or direct exe\nportableInvocation(\"C:\\tools\\mytool.exe\", args)","handlingStrategy":"try-catch","validationCode":"import { statSync } from \"node:fs\";\n\nfunction shimSafeToLaunch(command: string): boolean {\n  if (process.platform !== \"win32\" || !/\\.(?:cmd|bat)$/i.test(command)) return true;\n  try {\n    const s = statSync(command);\n    return s.isFile() && s.size <= 256 * 1024;\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const invocation = portableInvocation(cmd, args);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith(\"cannot safely launch Windows command shim\")) {\n    return spawnFallback(nativeExeFor(cmd), args); // prefer a native .exe\n  }\n  throw e;\n}","preventionTips":["Prefer native .exe distributions of tools on Windows.","Regenerate npm shims after partial installs instead of reusing suspect .cmd files.","Validate shim files are regular and small before delegating launch to caveman."],"tags":["windows","security","cli","shim"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}