{"record":{"id":"2510295a932d9f04","repo":"ruvnet/ruflo","slug":"command-not-allowed-cmd-split-0","errorCode":null,"errorMessage":"Command not allowed: ${cmd.split(' ')[0]}","messagePattern":"Command not allowed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/deployment/src/release-manager.ts","lineNumber":35,"sourceCode":"  'git tag',\n  'git add',\n  'git commit',\n  'git describe',\n];\n\n/**\n * Validate command against allowlist to prevent command injection\n */\nfunction validateCommand(cmd: string): void {\n  // Check for shell metacharacters\n  if (/[;&|`$()<>]/.test(cmd)) {\n    throw new Error(`Invalid command: contains shell metacharacters`);\n  }\n\n  // Must start with an allowed command prefix\n  const isAllowed = ALLOWED_GIT_COMMANDS.some(prefix => cmd.startsWith(prefix));\n  if (!isAllowed) {\n    throw new Error(`Command not allowed: ${cmd.split(' ')[0]}`);\n  }\n}\nimport type {\n  ReleaseOptions,\n  ReleaseResult,\n  PackageInfo,\n  GitCommit,\n  ChangelogEntry,\n  VersionBumpType\n} from './types.js';\n\nexport class ReleaseManager {\n  private cwd: string;\n\n  constructor(cwd: string = process.cwd()) {\n    this.cwd = cwd;\n  }\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/deployment/src/release-manager.ts#L17-L53","documentation":"validateCommand() in the release manager requires the command to start with one of the ALLOWED_GIT_COMMANDS prefixes (git status, git log, git tag, git add, git commit, git describe, and the other git-prefixed entries). The first word of any non-matching command is echoed back in the error so the caller can see which token was refused.","triggerScenarios":"A command string reaching ReleaseManager's execCommand that starts with anything but an allowlisted git subcommand — 'npm ...', 'ls', 'gh release ...', 'echo ...'.","commonSituations":"Extending the release flow to run npm or GitHub CLI steps through the same manager; patched or subclassed flows that assume the publisher's wider (npm/npx/pnpm/yarn) allowlist applies here too.","solutions":["Run npm-related steps through Publisher (which allows npm/npx/pnpm/yarn) and keep only git operations in ReleaseManager","Wrap non-git commands outside these classes with your own exec call rather than bypassing the allowlist","Check the ALLOWED_GIT_COMMANDS list in release-manager.ts before adding new internal steps"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const ALLOWED_GIT = ['git status', 'git log', 'git tag', 'git add', 'git commit', 'git describe'];\nfunction isAllowedGitCommand(cmd: string): boolean {\n  return ALLOWED_GIT.some(p => cmd.startsWith(p)) && !/[;&|`$()<>]/.test(cmd);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep only git operations in ReleaseManager; npm operations belong to Publisher","When extending release flows, add commands to the module allowlist rather than concatenating arbitrary strings"],"tags":["git","release","security","allowlist"],"backgroundTag":"command-allowlist-rejected","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}