ruvnet/ruflo · error
Invalid command: contains shell metacharacters
Error message
Invalid command: contains shell metacharacters
What it means
Validator.execCommand() — used to run the testCommand and buildCommand options of validate() — rejects any command containing ; & | ` $ ( ) < > before executing it with execSync. Chained commands, pipes, and substitutions are blocked rather than quoted.
Source
Thrown at v3/@claude-flow/deployment/src/validator.ts:275
}
/**
* Allowed commands for security validation
*/
private static readonly ALLOWED_COMMAND_PREFIXES = [
'npm run ',
'npm ',
'npx ',
'git ',
];
/**
* Execute command safely with validation
*/
private execCommand(cmd: string, returnOutput = false): string {
// Validate: check for shell metacharacters
if (/[;&|`$()<>]/.test(cmd)) {
throw new Error(`Invalid command: contains shell metacharacters`);
}
// Validate: must start with allowed prefix
const isAllowed = Validator.ALLOWED_COMMAND_PREFIXES.some(
prefix => cmd.startsWith(prefix)
);
if (!isAllowed) {
throw new Error(`Command not allowed: ${cmd.split(' ')[0]}`);
}
try {
const output = execSync(cmd, {
cwd: this.cwd,
encoding: 'utf-8',
stdio: returnOutput ? 'pipe' : 'inherit',
timeout: 60000, // 60 second timeout for builds
maxBuffer: 50 * 1024 * 1024, // 50MB buffer for build output
});View on GitHub (pinned to fa13ee4ad6)
Solutions
- Point testCommand/buildCommand at single package.json scripts: 'npm test', 'npm run build'
- Move any chaining inside the script definition itself, not into the command string passed to validate()
Example fix
// before
validate({ testCommand: 'npm run lint && npm test' }); // throws
// after
// package.json: "verify": "npm run lint && npm test"
validate({ testCommand: 'npm run verify' }); Defensive patterns
Strategy: validation
Validate before calling
function isValidatorSafeCommand(cmd: string): boolean {
return !/[;&|`$()<>]/.test(cmd) && ['npm run ', 'npm ', 'npx ', 'git '].some(p => cmd.startsWith(p));
}
if (!isValidatorSafeCommand(testCommand)) throw new Error('use a single npm script for testCommand');
await validate({ testCommand, buildCommand }); Prevention
- Reference one package.json script per validate() option — no chaining
- Keep pipes/redirects inside the script file, not in the command string
When it happens
Trigger: validate({ testCommand: 'npm test && npm run lint' }); buildCommand: 'npm run build 2>&1'; any option string containing &&, |, $( ), or redirection.
Common situations: Copying a combined lint+test line from CI config into ValidationOptions; build commands with subshells or output redirects.
Related errors
- Invalid GCS object path: ${objectPath}
- Invalid command: contains shell metacharacters
- Command not allowed: ${cmd.split(' ')[0]}
- Validation failed: ${result.error}
- Invalid container name: ${containerName}
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/bd4bbfbaf62312c3.
Report an issue: GitHub.