{"record":{"id":"452a91bad16d3a15","repo":"affaan-m/ECC","slug":"arguments-contain-unsafe-characters-args","errorCode":null,"errorMessage":"Arguments contain unsafe characters: ${args}","messagePattern":"Arguments contain unsafe characters: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/package-manager.js","lineNumber":338,"sourceCode":"// Allowed characters in arguments: alphanumeric, whitespace, dashes, dots, slashes,\n// equals, colons, commas, quotes, @. Rejects shell metacharacters like ; | & ` $ ( ) { } < > !\nconst SAFE_ARGS_REGEX = /^[@a-zA-Z0-9\\s_./:=,'\"*+-]+$/;\n\n/**\n * Get the command to execute a package binary\n * @param {string} binary - Binary name (e.g., \"prettier\", \"eslint\")\n * @param {string} args - Arguments to pass\n * @throws {Error} If binary name or args contain unsafe characters\n */\nfunction getExecCommand(binary, args = '', options = {}) {\n  if (!binary || typeof binary !== 'string') {\n    throw new Error('Binary name must be a non-empty string');\n  }\n  if (!SAFE_NAME_REGEX.test(binary)) {\n    throw new Error(`Binary name contains unsafe characters: ${binary}`);\n  }\n  if (args && typeof args === 'string' && !SAFE_ARGS_REGEX.test(args)) {\n    throw new Error(`Arguments contain unsafe characters: ${args}`);\n  }\n\n  const pm = getPackageManager(options);\n  return `${pm.config.execCmd} ${binary}${args ? ' ' + args : ''}`;\n}\n\n/**\n * Interactive prompt for package manager selection\n * Returns a message for Claude to show to user\n *\n * NOTE: Does NOT spawn child processes to check availability.\n * Lists all supported PMs and shows how to configure preference.\n */\nfunction getSelectionPrompt() {\n  let message = '[PackageManager] No package manager preference detected.\\n';\n  message += 'Supported package managers: ' + Object.keys(PACKAGE_MANAGERS).join(', ') + '\\n';\n  message += '\\nTo set your preferred package manager:\\n';\n  message += '  - Global: Set CLAUDE_PACKAGE_MANAGER environment variable\\n';","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/package-manager.js#L320-L356","documentation":"getExecCommand() validates its optional args string against SAFE_ARGS_REGEX after checking the binary name. This error is thrown when args is a non-empty string containing characters the library considers unsafe for command-line interpolation (quotes, semicolons, command substitution, unescaped specials). It guards the generated command `${execCmd} ${binary} ${args}` against shell injection.","triggerScenarios":"Calling getExecCommand('eslint', args) where args contains disallowed characters — e.g. getExecCommand('eslint', \"--rule '{x: y}'\"), getExecCommand('jest', '--testPathPattern=$(whoami)'), getExecCommand('prettier', '--plugin a;b').","commonSituations":"Quoted flag values with spaces or single quotes (rules, regexes, commit messages) pasted into args; interpolating file lists, branch names, or user text into args; multi-command strings ('a && b'); Windows-vs-POSIX quoting differences causing flags to look unsafe.","solutions":["Simplify args to plain flags and safe values ('--fix', '--check .') and remove quoting/metacharacters the regex rejects.","Pass variable data through a supported option or config file instead of inline command-line values (e.g. put complex rules in a config file and pass '--config file').","Inspect the offending args in the message and split: keep static flags in args, move dynamic values into validated inputs or files.","If the value is legitimately needed and safe, escape it per the library's SAFE_ARGS_REGEX expectations, or contribute/extend the allowlist consciously."],"exampleFix":"// before\ngetExecCommand('eslint', `--rule \"${userRule}\"`)\n// after\n// write the rule to a temp config file instead of inline quoting\ngetExecCommand('eslint', `--config ${safeConfigPath}`)","handlingStrategy":"validation","validationCode":"const SAFE_ARGS = /^[A-Za-z0-9 .,=_:\\/@+-]*$/;\nif (args && !SAFE_ARGS.test(args)) {\n  throw new Error(`Unsafe arguments: ${args}`);\n}\ngetExecCommand(binary, args);","typeGuard":"function isSafeArgsString(v) {\n  return v == null || (typeof v === 'string' && /^[A-Za-z0-9 .,=_:\\/@+-]*$/.test(v));\n}","tryCatchPattern":"try {\n  const cmd = getExecCommand(binary, args);\n} catch (e) {\n  if (String(e.message).startsWith('Arguments contain unsafe characters')) {\n    console.error(`Move dynamic values (rules, paths, messages) out of inline args: ${args}`);\n  } else throw e;\n}","preventionTips":["Keep args to static flags; route dynamic values through config files or validated options.","Never interpolate user text, commit messages, or regexes directly into args.","Avoid chained commands ('&&', ';') — one tool invocation per call.","Prefer long-form flags without quoting; complex values belong in files passed via --config/--flag-file."],"tags":["validation","shell-injection-prevention","command-line","argument-sanitization"],"backgroundTag":"invalid-argument-value","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"}