affaan-m/ECC · error

Arguments contain unsafe characters

Error message

Arguments contain unsafe characters: ${args}

What it means

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.

Solutions

  1. Simplify args to plain flags and safe values ('--fix', '--check .') and remove quoting/metacharacters the regex rejects.
  2. 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').
  3. Inspect the offending args in the message and split: keep static flags in args, move dynamic values into validated inputs or files.
  4. If the value is legitimately needed and safe, escape it per the library's SAFE_ARGS_REGEX expectations, or contribute/extend the allowlist consciously.

Example fix

// before
getExecCommand('eslint', `--rule "${userRule}"`)
// after
// write the rule to a temp config file instead of inline quoting
getExecCommand('eslint', `--config ${safeConfigPath}`)
Defensive patterns

Strategy: validation

Validate before calling

const SAFE_ARGS = /^[A-Za-z0-9 .,=_:\/@+-]*$/;
if (args && !SAFE_ARGS.test(args)) {
  throw new Error(`Unsafe arguments: ${args}`);
}
getExecCommand(binary, args);

Type guard

function isSafeArgsString(v) {
  return v == null || (typeof v === 'string' && /^[A-Za-z0-9 .,=_:\/@+-]*$/.test(v));
}

Try / catch

try {
  const cmd = getExecCommand(binary, args);
} catch (e) {
  if (String(e.message).startsWith('Arguments contain unsafe characters')) {
    console.error(`Move dynamic values (rules, paths, messages) out of inline args: ${args}`);
  } else throw e;
}

Prevention

When it happens

Trigger: 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').

Common situations: 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.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/452a91bad16d3a15. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/package-manager.js:338

// 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';
  message += 'Supported package managers: ' + Object.keys(PACKAGE_MANAGERS).join(', ') + '\n';
  message += '\nTo set your preferred package manager:\n';
  message += '  - Global: Set CLAUDE_PACKAGE_MANAGER environment variable\n';

View on GitHub (pinned to 8321021c54)