ruvnet/ruflo · error · Error
Disallowed command: only npm/npx/pnpm/yarn commands are perm
Error message
Disallowed command: only npm/npx/pnpm/yarn commands are permitted
What it means
Publisher.execCommand() — used to run the buildCommand option of publishToNpm() — only accepts strings starting with 'npm run ', 'npm ', 'npx ', 'pnpm ', or 'yarn '. Anything else is treated as a potential command injection and rejected before the build executes.
Source
Thrown at v3/@claude-flow/deployment/src/publisher.ts:224
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 {
// Only allow npm/npx build commands for safety
const allowedPrefixes = ['npm run ', 'npm ', 'npx ', 'pnpm ', 'yarn '];
const isAllowed = allowedPrefixes.some(prefix => cmd.startsWith(prefix));
if (!isAllowed) {
throw new Error(`Disallowed command: only npm/npx/pnpm/yarn commands are permitted`);
}
// Validate no dangerous shell metacharacters
if (/[;&|`$()<>]/.test(cmd)) {
throw new Error(`Invalid command: contains shell metacharacters`);
}
try {
const output = execSync(cmd, {
cwd: this.cwd,
encoding: 'utf-8',
stdio: returnOutput ? 'pipe' : 'inherit'
});
return returnOutput ? output : '';
} catch (error) {
throw error;
}
}
}
View on GitHub (pinned to fa13ee4ad6)
Solutions
- Move the build into package.json scripts ("scripts": { "build": "node build.js" }) and pass buildCommand: 'npm run build'
- Or use an allowlisted prefix form: 'npx tsc -p .', 'pnpm build', 'yarn build'
- Or pass skipBuild: true and run your custom build yourself before calling publishToNpm
Example fix
// before
await publisher.publishToNpm({ buildCommand: 'node ./scripts/bundle.js' }); // throws
// after
// package.json: "scripts": { "build": "node ./scripts/bundle.js" }
await publisher.publishToNpm({ buildCommand: 'npm run build' }); Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = ['npm run ', 'npm ', 'npx ', 'pnpm ', 'yarn '];
function isAllowedBuildCommand(cmd: string): boolean {
return ALLOWED.some(p => cmd.startsWith(p)) && !/[;&|`$()<>]/.test(cmd);
}
if (!isAllowedBuildCommand(buildCommand)) buildCommand = 'npm run build';
await publisher.publishToNpm({ buildCommand }); Prevention
- Express every build as an npm script so the default 'npm run build' just works
- Never pass node/make/shell-script paths as buildCommand
When it happens
Trigger: publishToNpm({ buildCommand: 'node build.js' }), 'make build', './scripts/build.sh', or 'tsc -p .' — none matches an allowed prefix.
Common situations: Packages whose build is a plain node script or make target; migrating a hand-rolled release script that invoked the build directly.
Related errors
- Invalid argument: contains shell metacharacters
- Invalid command: contains shell metacharacters
- Command not allowed: ${cmd.split(' ')[0]}
- 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/536b70ed34c9c05a.
Report an issue: GitHub.