affaan-m/ECC · error · Error
Script name contains unsafe characters: ${script}
Error message
Script name contains unsafe characters: ${script} What it means
Thrown by getRunCommand() when the script name is a string but fails SAFE_NAME_REGEX = /^[@a-zA-Z0-9_./-]+$/. This is the shell-injection guard: it rejects metacharacters like ; | & ` $ ( ) while still permitting scoped package names (@scope/pkg) and slashes.
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 01e15490f0)
Solutions
- Pass flags via getExecCommand(binary, args) instead of stuffing them into the script name.
- Strip or reject non-whitelist characters before calling: keep only [@a-zA-Z0-9_./-].
- Use a fixed allowlist of script names you accept from untrusted input.
- If a script name legitimately contains other characters, alias it in package.json and call the alias.
Example fix
// before
getRunCommand('test --watch', opts); // space rejected
// after
getRunCommand('test', opts) + ' --watch'; // flags appended by caller
// or define "test:watch" in package.json and call that Defensive patterns
Strategy: validation
Validate before calling
const SAFE_NAME = /^[@a-zA-Z0-9_.\/-]+$/;
if (!SAFE_NAME.test(script)) {
throw new Error(`Rejected script name: ${script}`);
}
getRunCommand(script, opts); Prevention
- Treat the script name as untrusted input; never interpolate user text into it.
- Restrict dynamic script names to an allowlist from package.json.
- Route flags through args, not the script name.
When it happens
Trigger: Passing a script name containing spaces, shell metacharacters, parentheses, or quotes, e.g. getRunCommand('test; rm -rf /'), getRunCommand('build && deploy'), getRunCommand('my script'), getRunCommand('$(whoami)'). Any user-controlled or env-derived script name that was not sanitized.
Common situations: Concatenating user input into a script name; a config file or environment variable carrying a tainted value; a script name with a space from a copy-paste; an attempt to pass CLI flags through the script argument instead of a dedicated args path.
Related errors
- Binary name contains unsafe characters: ${binary}
- Arguments contain unsafe characters: ${args}
- Claude Code command contains characters that are unsafe for
- Unknown package manager: ${pmName}
- Script name must be a non-empty string
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/5325f167b12be428.
Report an issue: GitHub.