{"record":{"id":"fbf6b7f9f2eb9ce1","repo":"CherryHQ/cherry-studio","slug":"invalid-command-command-cannot-be-empty","errorCode":null,"errorMessage":"Invalid command: command cannot be empty","messagePattern":"Invalid command: command cannot be empty","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/mcp/McpPackageService.ts","lineNumber":147,"sourceCode":" * Commands should be either:\n * 1. Simple command names (e.g., \"node\", \"python\", \"npx\") - looked up in PATH\n * 2. Absolute paths (e.g., \"/usr/bin/node\", \"C:\\\\Program Files\\\\node\\\\node.exe\")\n * 3. Relative paths starting with ./ or .\\ (relative to extractDir)\n *\n * Rejects commands containing path traversal sequences (..)\n *\n * @param command - The command to validate\n * @returns The validated command\n * @throws Error if command contains path traversal or is invalid\n */\nexport function validateCommand(command: string): string {\n  if (!command || typeof command !== 'string') {\n    throw new Error('Invalid command: command must be a non-empty string')\n  }\n\n  const trimmed = command.trim()\n  if (!trimmed) {\n    throw new Error('Invalid command: command cannot be empty')\n  }\n\n  // Check for path traversal sequences\n  // This catches: .., ../, ..\\, /../, \\..\\, etc.\n  if (/(?:^|[/\\\\])\\.\\.(?:[/\\\\]|$)/.test(trimmed) || trimmed === '..') {\n    throw new Error(`Invalid command: path traversal detected in \"${command}\"`)\n  }\n\n  // Check for null bytes\n  if (trimmed.includes('\\0')) {\n    throw new Error('Invalid command: null byte detected')\n  }\n\n  return trimmed\n}\n\n/**\n * Validate command arguments to prevent injection attacks.","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/mcp/McpPackageService.ts#L129-L165","documentation":"Thrown by validateCommand() after trimming the command string, when the trimmed result is empty. This distinguishes from the non-empty-string check (error 153): the input was technically a string but contained only whitespace characters (spaces, tabs, newlines). The trimmed command is the return value of validateCommand, so a whitespace-only command would produce an empty executable name.","triggerScenarios":"Called from resolveMcpConfig at line 351. Triggers when the manifest's command field is a string like '   ', '\\t\\n', or any combination of whitespace-only characters. After performVariableSubstitution, a command like '${user_config.executor}' that resolved to whitespace would also hit this.","commonSituations":"A manifest author left a placeholder command that was never filled in; variable substitution replaced a template with an empty/whitespace user-config value; copy-paste from a formatted document introduced stray whitespace.","solutions":["Set the manifest's command to a real executable name (e.g., 'node', 'python', 'npx', or an absolute path).","If using variable substitution, verify the substitution source (user_config) provides a non-empty value.","Validate the manifest with a schema that enforces minLength: 1 on the command field."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-validate that command is not whitespace-only\nif (typeof command === 'string' && command.trim().length === 0) {\n  throw new Error('Manifest command field cannot be whitespace-only')\n}","typeGuard":"function isNonEmptyTrimmedString(value: unknown): value is string {\n  return typeof value === 'string' && value.trim().length > 0\n}","tryCatchPattern":null,"preventionTips":["Enforce minLength: 1 with a trim transform in the manifest schema validator.","Test manifest command fields with whitespace-only values to confirm they are caught.","When authoring manifests, use real executable names — never placeholders."],"tags":["validation","mcp","command-injection","manifest"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}