{"record":{"id":"a54faa4fe72e1071","repo":"affaan-m/ECC","slug":"file-path-contains-unsafe-shell-characters","errorCode":null,"errorMessage":"File path contains unsafe shell characters","messagePattern":"File path contains unsafe shell characters","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/hooks/post-edit-format.js","lineNumber":60,"sourceCode":"    if (filePath && /\\.(ts|tsx|js|jsx)$/.test(filePath)) {\n      try {\n        const resolvedFilePath = path.resolve(filePath);\n        const projectRoot = findProjectRoot(path.dirname(resolvedFilePath));\n        const formatter = detectFormatter(projectRoot);\n        if (!formatter) return rawInput;\n\n        const resolved = resolveFormatterBin(projectRoot, formatter);\n        if (!resolved) return rawInput;\n\n        // Biome: `check --write` = format + lint in one pass\n        // Prettier: `--write` = format only\n        const args = formatter === 'biome' ? [...resolved.prefix, 'check', '--write', resolvedFilePath] : [...resolved.prefix, '--write', resolvedFilePath];\n\n        if (process.platform === 'win32' && resolved.bin.endsWith('.cmd')) {\n          // Windows: .cmd files require shell to execute. Guard against\n          // command injection by rejecting paths with shell metacharacters.\n          if (UNSAFE_PATH_CHARS.test(resolvedFilePath)) {\n            throw new Error('File path contains unsafe shell characters');\n          }\n          const result = spawnSync(resolved.bin, args, {\n            cwd: projectRoot,\n            shell: true,\n            stdio: 'pipe',\n            timeout: 15000\n          });\n          if (result.error) throw result.error;\n          if (typeof result.status === 'number' && result.status !== 0) {\n            throw new Error(result.stderr?.toString() || `Formatter exited with status ${result.status}`);\n          }\n        } else {\n          execFileSync(resolved.bin, args, {\n            cwd: projectRoot,\n            stdio: ['pipe', 'pipe', 'pipe'],\n            timeout: 15000\n          });\n        }","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/hooks/post-edit-format.js#L42-L78","documentation":"post-edit-format.js throws this on Windows when the formatter binary is a .cmd file and must be spawned with shell:true. Because the shell enables command injection, the hook rejects file paths matching UNSAFE_PATH_CHARS (shell metacharacters such as quotes, &, |, ;) before spawning.","triggerScenarios":"Editing a file on Windows whose path contains `&`, `|`, `;`, quotes, or other shell metacharacters, then triggering the PostToolUse format hook with a .cmd formatter such as biome.cmd.","commonSituations":"Project or temp directories with `&` or parentheses in their names, files created with quoted names, npm .cmd shims being resolved as the formatter binary on Windows.","solutions":["Rename the file or move the project to a path without shell metacharacters","Use a non-.cmd formatter binary (node script or .exe) so shell:true is not needed","Run the formatter manually (`npx biome check --write <file>`) for this file","Fix PATH so a plain non-.cmd binary is resolved"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const UNSAFE_PATH_CHARS = /[&|;<>()\"'`^%$!{}\\[\\],=?~*\\s]/; // match hook's set\nif (process.platform === 'win32' && !UNSAFE_PATH_CHARS.test(filePath)) {\n  formatFile(filePath); // safe to proceed\n}","typeGuard":null,"tryCatchPattern":"try {\n  run({ filePath });\n} catch (err) {\n  if (err.message === 'File path contains unsafe shell characters') {\n    console.warn(`Skipping shell-based format for: ${filePath}`);\n    return; // skip or format via non-shell path\n  }\n  throw err;\n}","preventionTips":["Avoid shell metacharacters in project and file names, especially on Windows","Prefer invoking formatters via `node <bin-js>` or .exe over .cmd shims","Keep formatter resolution aware of platform so shell:true is only used when unavoidable"],"tags":["security","windows","shell-injection","hooks"],"backgroundTag":"shell-injection-guard","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}