ruvnet/ruflo · error · Error
Invalid argument: contains shell metacharacters
Error message
Invalid argument: contains shell metacharacters
What it means
execNpmCommand() rejects any argument containing ; & | ` $ ( ) < > before spawning npm — even though it uses execFileSync with shell: false. It is a defense-in-depth injection guard, so values that are harmless under shell:false but merely contain those characters (Windows paths with parentheses, decorated dist-tags) are rejected too.
Source
Thrown at v3/@claude-flow/deployment/src/publisher.ts:201
const output = this.execNpmCommand(packArgs, true);
const tarballName = output.trim().split('\n').pop() || '';
return outputDir ? join(outputDir, tarballName) : tarballName;
} catch (error) {
throw new Error(`Failed to pack: ${error}`);
}
}
/**
* Execute npm command safely using execFileSync
*/
private execNpmCommand(args: string[], returnOutput = false): string {
try {
// Validate args don't contain shell metacharacters
for (const arg of args) {
if (/[;&|`$()<>]/.test(arg)) {
throw new Error(`Invalid argument: contains shell metacharacters`);
}
}
const output = execFileSync('npm', args, {
cwd: this.cwd,
encoding: 'utf-8',
shell: false,
stdio: returnOutput ? ['pipe', 'pipe', 'pipe'] : 'inherit'
});
return returnOutput ? output : '';
} catch (error) {
throw error;
}
}
/**
* Execute command (for build scripts only - validated)
*/
private execCommand(cmd: string, returnOutput = false): string {View on GitHub (pinned to fa13ee4ad6)
Solutions
- Restrict tag and outputDir values to [A-Za-z0-9._-]: use 'beta-1' not 'beta (1)', 'next-rc1' not 'next$(date)'
- Choose an outputDir without parentheses or special characters, or omit outputDir and move the resulting tarball yourself
- Pre-validate with the same class /[;&|`$()<>]/ before calling pack/publishToNpm so you control the error message
Example fix
// before
await publisher.publishToNpm({ tag: 'release (main)' }); // throws: shell metacharacters
// after
await publisher.publishToNpm({ tag: 'release-main' }); Defensive patterns
Strategy: validation
Validate before calling
const METACHARS = /[;&|`$()<>]/;
function isSafeNpmArg(value: string): boolean {
return typeof value === 'string' && value.length > 0 && !METACHARS.test(value);
}
if (!isSafeNpmArg(tag)) throw new Error('tag contains shell metacharacters');
await publisher.publishToNpm({ tag }); Prevention
- Generate dist-tags and paths from [A-Za-z0-9._-] only
- Sanitize branch/PR-derived values before using them as npm tags or destinations
When it happens
Trigger: publishToNpm({ tag: 'next$(whoami)' }) or any tag/registry/otp string containing ()<>|&`$; pack('dir (1)') with parentheses in the outputDir; branch-derived tag names like 'feature/fix-(auth)'.
Common situations: Windows directories with parentheses (e.g. 'Dir (1)'); automated tag names built from branch or PR titles; release scripts interpolating versions like '1.0.0-beta(1)'.
Related errors
- Invalid git ref: contains unsafe characters
- Disallowed command: only npm/npx/pnpm/yarn commands are perm
- signAttributionArtifact: privateKey must be 32 bytes (got ${
- AIDefence package not available. Install with: npm install @
- AIDefence installed but failed to load: ${retryError}. This
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/174aa213cf461bb2.
Report an issue: GitHub.