{"record":{"id":"7871c438b1e4e4df","repo":"FlowiseAI/Flowise","slug":"argument-arg-contains-dangerous-flag-ch","errorCode":null,"errorMessage":"Argument '${arg}' contains dangerous flag '-${ch}' for command '${command}'.","messagePattern":"Argument '(.+?)' contains dangerous flag '-(.+?)' for command '(.+?)'\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/tools/MCP/core.ts","lineNumber":402,"sourceCode":"            const lowerCaseFlag = flag.toLowerCase()\n            if (normalizedArg === lowerCaseFlag) {\n                throw new Error(`Argument '${arg}' is not allowed for command '${command}'.`)\n            }\n            if (normalizedArg.startsWith(lowerCaseFlag + '=')) {\n                throw new Error(`Argument '${arg}' contains flag '${flag}' that is not allowed for command '${command}'.`)\n            }\n            if (flag.startsWith('-') && normalizedArg.startsWith(lowerCaseFlag + ' ')) {\n                throw new Error(`Argument '${arg}' contains flag '${flag}' that is not allowed for command '${command}'.`)\n            }\n        }\n\n        // Check for combined short flags (e.g. \"-yc\" = \"-y\" + \"-c\")\n        // A combined flag starts with a single '-', is not a long flag '--', and has multiple characters after '-'\n        if (/^-[a-zA-Z]{2,}/.test(normalizedArg)) {\n            const flagChars = normalizedArg.slice(1) // strip leading '-'\n            for (const ch of flagChars) {\n                if (dangerousShortChars.has(ch)) {\n                    throw new Error(`Argument '${arg}' contains dangerous flag '-${ch}' for command '${command}'.`)\n                }\n            }\n        }\n    }\n}\n\n/**\n * Validates a user-supplied MCP server configuration against operator-controlled allow-lists.\n *\n * For stdio configs, the command must appear in the `CUSTOM_MCP_ALLOWED_COMMANDS` allow-list\n * (comma-separated, empty = none allowed). The list is empty by default, so no command can run\n * until an operator explicitly opts in. To enable local/custom stdio MCP servers, set\n * `CUSTOM_MCP_PROTOCOL=stdio` and `CUSTOM_MCP_ALLOWED_COMMANDS` in your env file\n * (see docker/.env.example, docker/worker/.env.example, packages/server/.env.example).\n */\nexport const validateMCPServerConfig = (serverParams: any): void => {\n    // Validate the entire server configuration\n    if (!serverParams || typeof serverParams !== 'object') {","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/tools/MCP/core.ts#L384-L420","documentation":"Thrown by validateCommandFlags during the combined-short-flag check. After the per-flag loop, if an arg matches /^-[a-zA-Z]{2,}/ (a multi-char short flag bundle like '-yc'), the code splits off the '-' and iterates each character; if any char is in dangerousShortChars (the single-letter dangerous flags like 'c' for npx/python, 'e'/'p'/'r' for node, 'v' for docker) it throws naming the offending '-<ch>'.","triggerScenarios":"An arg bundles a dangerous short flag with others, e.g. npx '-yc' (auto-confirm + execute), node '-pe' (print + eval), python '-mc'. The earlier exact-match and =/space checks miss this, so the dedicated combined-flag scan catches it.","commonSituations":"Operator tries to hide '-c' inside '-yc' to bypass the exact-flag guard; legitimate combined flags that happen to include a dangerous letter (e.g. '-vc').","solutions":["Unbundle combined short flags and remove any dangerous ones.","Avoid '-c' entirely for npx/python/python3 and '-e'/'-p'/'-r' for node.","If a combined flag is legitimate but includes a dangerous letter, restructure so the dangerous capability is not invoked."],"exampleFix":"// before\n{ command: 'npx', args: ['-yc', 'pkg'] }\n\n// after\n{ command: 'npx', args: ['pkg'] } // no auto-confirm+exec bundle","handlingStrategy":"validation","validationCode":"const dangerousShort = new Set(['c', 'e', 'p', 'r', 'v']) // single-letter dangerous flags per command\nif (args.some(a => /^-[a-zA-Z]{2,}/.test(a) && a.slice(1).split('').some(ch => dangerousShort.has(ch.toLowerCase())))) {\n  throw new Error('Arg bundles a dangerous short flag')\n}","typeGuard":"const argsHaveNoDangerousBundledShortFlags = (args: string[], dangerousShort: Set<string>): boolean =>\n  !args.some(a => typeof a === 'string' && /^-[a-zA-Z]{2,}/.test(a) && a.slice(1).split('').some(ch => dangerousShort.has(ch.toLowerCase())))","tryCatchPattern":"try {\n  validateCommandFlags(command, args)\n} catch (e) {\n  if (e.message.includes('contains dangerous flag')) {\n    // unbundle the short flags and drop the dangerous one\n  }\n  throw e\n}","preventionTips":["Never bundle short flags for commands that have dangerous single-letter flags.","Normalize args so each flag stands alone before validation.","Add a unit test for combined-flag evasion attempts."],"tags":["mcp","security","command-flags","injection"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}