affaan-m/ECC · error
Script name contains unsafe characters
Error message
Script name contains unsafe characters: ${script} What it means
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.
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.
Example fix
// before
getRunCommand(`test --grep "${pattern}"`)
// after
getRunCommand('test') // pass pattern via the runner's own arg mechanism
getExecCommand('jest', '--grep', { pattern: 'safe-pattern' }) Defensive patterns
Strategy: validation
Validate before calling
const SAFE_NAME = /^[A-Za-z0-9@/._-]+$/;
if (typeof script !== 'string' || !SAFE_NAME.test(script)) {
throw new Error(`Invalid script name: ${JSON.stringify(script)}`);
}
getRunCommand(script); Type guard
function isSafeScriptName(v) {
return typeof v === 'string' && /^[A-Za-z0-9@/._-]+$/.test(v);
} Try / catch
try {
const cmd = getRunCommand(script);
} catch (e) {
if (String(e.message).startsWith('Script name contains unsafe characters')) {
console.error(`Rejecting script name: ${script}. Use a bare script name without flags or shell metacharacters.`);
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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").
Common situations: 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.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Binary name contains unsafe characters
- Arguments contain unsafe characters
- Binary name must be a non-empty string
- Unknown package manager
- -32602
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/5325f167b12be428.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/package-manager.js:301
return config;
}
// Allowed characters in script/binary names: alphanumeric, dash, underscore, dot, slash, @
// This prevents shell metacharacter injection while allowing scoped packages (e.g., @scope/pkg)
const SAFE_NAME_REGEX = /^[@a-zA-Z0-9_./-]+$/;
/**
* Get the command to run a script
* @param {string} script - Script name (e.g., "dev", "build", "test")
* @param {object} options - { projectDir }
* @throws {Error} If script name contains unsafe characters
*/
function getRunCommand(script, options = {}) {
if (!script || typeof script !== 'string') {
throw new Error('Script name must be a non-empty string');
}
if (!SAFE_NAME_REGEX.test(script)) {
throw new Error(`Script name contains unsafe characters: ${script}`);
}
const pm = getPackageManager(options);
switch (script) {
case 'install':
return pm.config.installCmd;
case 'test':
return pm.config.testCmd;
case 'build':
return pm.config.buildCmd;
case 'dev':
return pm.config.devCmd;
default:
return `${pm.config.runCmd} ${script}`;
}
}
View on GitHub (pinned to 8321021c54)