{"record":{"id":"5325f167b12be428","repo":"affaan-m/ECC","slug":"script-name-contains-unsafe-characters-script","errorCode":null,"errorMessage":"Script name contains unsafe characters: ${script}","messagePattern":"Script name contains unsafe characters: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/package-manager.js","lineNumber":301,"sourceCode":"  return config;\n}\n\n// Allowed characters in script/binary names: alphanumeric, dash, underscore, dot, slash, @\n// This prevents shell metacharacter injection while allowing scoped packages (e.g., @scope/pkg)\nconst SAFE_NAME_REGEX = /^[@a-zA-Z0-9_./-]+$/;\n\n/**\n * Get the command to run a script\n * @param {string} script - Script name (e.g., \"dev\", \"build\", \"test\")\n * @param {object} options - { projectDir }\n * @throws {Error} If script name contains unsafe characters\n */\nfunction getRunCommand(script, options = {}) {\n  if (!script || typeof script !== 'string') {\n    throw new Error('Script name must be a non-empty string');\n  }\n  if (!SAFE_NAME_REGEX.test(script)) {\n    throw new Error(`Script name contains unsafe characters: ${script}`);\n  }\n\n  const pm = getPackageManager(options);\n\n  switch (script) {\n    case 'install':\n      return pm.config.installCmd;\n    case 'test':\n      return pm.config.testCmd;\n    case 'build':\n      return pm.config.buildCmd;\n    case 'dev':\n      return pm.config.devCmd;\n    default:\n      return `${pm.config.runCmd} ${script}`;\n  }\n}\n","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/package-manager.js#L283-L319","documentation":"getRunCommand() builds the shell command for running a package-manager script (npm/pnpm/yarn/bun run <script>). Before doing anything it validates the script name against SAFE_NAME_REGEX and throws this error when the name contains characters outside the safe allowlist (letters, digits, hyphens, slashes, @, ., etc.). The library throws it to prevent shell metacharacters in caller-supplied names from being injected into a generated command line.","triggerScenarios":"Calling getRunCommand(script) where script is a non-empty string that fails SAFE_NAME_REGEX — e.g. containing spaces, semicolons, backticks, '$()', '&&', quotes, or other shell metacharacters. Examples: getRunCommand('test --grep foo'), getRunCommand('build; rm -rf /'), getRunCommand(\"test'x\").","commonSituations":"Script names built by string concatenation with flags or arguments appended ('test -- --watch' instead of passing watch separately); interpolating user input or CLI arguments into the script name; copy-pasted command lines rather than bare script names; automated tooling that forwards raw terminal strings as the script parameter.","solutions":["Pass only the bare script name ('test', 'build:fast') and move flags/arguments to a separate mechanism (e.g. the runner's argument options or getExecCommand with validated args).","Inspect the offending value printed in the message and remove shell metacharacters; the regex only allows a safe name charset.","If the script lives in a workspace, use the package/workspace selector supported by the detected package manager rather than embedding 'cd x && ...' in the name.","Sanitize or reject upstream input (CLI args, config values) before it reaches getRunCommand; validate with the same allowlist pattern."],"exampleFix":"// before\ngetRunCommand(`test --grep \"${pattern}\"`)\n// after\ngetRunCommand('test') // pass pattern via the runner's own arg mechanism\ngetExecCommand('jest', '--grep', { pattern: 'safe-pattern' })","handlingStrategy":"validation","validationCode":"const SAFE_NAME = /^[A-Za-z0-9@/._-]+$/;\nif (typeof script !== 'string' || !SAFE_NAME.test(script)) {\n  throw new Error(`Invalid script name: ${JSON.stringify(script)}`);\n}\ngetRunCommand(script);","typeGuard":"function isSafeScriptName(v) {\n  return typeof v === 'string' && /^[A-Za-z0-9@/._-]+$/.test(v);\n}","tryCatchPattern":"try {\n  const cmd = getRunCommand(script);\n} catch (e) {\n  if (String(e.message).startsWith('Script name contains unsafe characters')) {\n    console.error(`Rejecting script name: ${script}. Use a bare script name without flags or shell metacharacters.`);\n  } else throw e;\n}","preventionTips":["Never concatenate flags or arguments into the script name; keep it a bare identifier.","Never pass raw user/CLI input as the script name without allowlist validation.","Centralize script invocation through one helper that validates names once.","Add a unit test asserting known metacharacters (';', '$(', '`', spaces) are rejected early."],"tags":["validation","shell-injection-prevention","package-manager","argument-sanitization"],"backgroundTag":"invalid-identifier-format","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"}