affaan-m/ECC · error
Binary name contains unsafe characters
Error message
Binary name contains unsafe characters: ${binary} What it means
getExecCommand() validates the binary name against SAFE_NAME_REGEX before building the shell command. This error is thrown when the binary is a proper non-empty string but contains characters outside the safe allowlist (spaces, '/', path separators in some forms, quotes, ';', '$()', etc.). It exists to stop untrusted binary names from injecting shell commands.
Solutions
- Pass only the bare binary token ('prettier', 'eslint') and move arguments to the args parameter (validated separately).
- Remove shell metacharacters from the value; check the offending name in the error message.
- If you need a specific binary path, use an API that accepts an absolute path or executable directly rather than embedding flags/paths with spaces here.
- Sanitize at the boundary: validate tool names from config/user input with the same allowlist before calling.
Example fix
// before
getExecCommand(`node ${scriptPath} --fix`)
// after
getExecCommand('node', `${scriptPath} --fix`) // args validated by SAFE_ARGS_REGEX Defensive patterns
Strategy: validation
Validate before calling
const SAFE_BINARY = /^[A-Za-z0-9._-]+$/;
if (!SAFE_BINARY.test(binary)) {
throw new Error(`Unsafe binary name: ${binary}`);
}
getExecCommand(binary, args); Type guard
function isSafeBinaryName(v) {
return typeof v === 'string' && /^[A-Za-z0-9._-]+$/.test(v);
} Try / catch
try {
const cmd = getExecCommand(binary, args);
} catch (e) {
if (String(e.message).startsWith('Binary name contains unsafe characters')) {
console.error(`Split '${binary}' into a bare binary plus args before calling.`);
} else throw e;
} Prevention
- Keep binary and arguments as separate parameters — never embed flags in the binary token.
- Avoid inline 'node -e' / 'sh -c' style invocations through this API.
- Validate any config- or user-supplied tool name against an allowlist at the boundary.
- Watch for paths with spaces; use the library's supported path mechanism, not the binary slot.
When it happens
Trigger: Calling getExecCommand with a binary value containing metacharacters or whitespace: getExecCommand('prettier --write'), getExecCommand('node -e x'), getExecCommand('/usr/bin/tool; rm -rf /'), getExecCommand('tool`id`').
Common situations: Concatenating a binary name with its arguments into one string; putting a full path with spaces into the binary slot; forwarding user-controlled input (CLI arg, config) as the binary; attempting to run inline scripts via 'node -e' or 'sh -c' through this API instead of a dedicated spawn API.
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
- Script 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/7431f17f769da684.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/package-manager.js:335
}
}
// Allowed characters in arguments: alphanumeric, whitespace, dashes, dots, slashes,
// equals, colons, commas, quotes, @. Rejects shell metacharacters like ; | & ` $ ( ) { } < > !
const SAFE_ARGS_REGEX = /^[@a-zA-Z0-9\s_./:=,'"*+-]+$/;
/**
* Get the command to execute a package binary
* @param {string} binary - Binary name (e.g., "prettier", "eslint")
* @param {string} args - Arguments to pass
* @throws {Error} If binary name or args contain unsafe characters
*/
function getExecCommand(binary, args = '', options = {}) {
if (!binary || typeof binary !== 'string') {
throw new Error('Binary name must be a non-empty string');
}
if (!SAFE_NAME_REGEX.test(binary)) {
throw new Error(`Binary name contains unsafe characters: ${binary}`);
}
if (args && typeof args === 'string' && !SAFE_ARGS_REGEX.test(args)) {
throw new Error(`Arguments contain unsafe characters: ${args}`);
}
const pm = getPackageManager(options);
return `${pm.config.execCmd} ${binary}${args ? ' ' + args : ''}`;
}
/**
* Interactive prompt for package manager selection
* Returns a message for Claude to show to user
*
* NOTE: Does NOT spawn child processes to check availability.
* Lists all supported PMs and shows how to configure preference.
*/
function getSelectionPrompt() {
let message = '[PackageManager] No package manager preference detected.\n';View on GitHub (pinned to 8321021c54)