{"record":{"id":"1177cc5b92f481f4","repo":"FlowiseAI/Flowise","slug":"security-validation-failed-error-message","errorCode":null,"errorMessage":"Security validation failed: ${error.message}","messagePattern":"Security validation failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts","lineNumber":180,"sourceCode":"                return cachedResult.tools\n            }\n        }\n\n        try {\n            let serverParams\n            if (typeof mcpServerConfig === 'object') {\n                serverParams = substituteVariablesInObject(mcpServerConfig, sandbox)\n            } else if (typeof mcpServerConfig === 'string') {\n                const substitutedString = substituteVariablesInString(mcpServerConfig, sandbox)\n                const serverParamsString = convertToValidJSONString(substitutedString)\n                serverParams = JSON.parse(serverParamsString)\n            }\n\n            if (process.env.CUSTOM_MCP_SECURITY_CHECK !== 'false') {\n                try {\n                    validateMCPServerConfig(serverParams)\n                } catch (error) {\n                    throw new Error(`Security validation failed: ${error.message}`)\n                }\n            }\n\n            // Compatible with stdio and SSE\n            let toolkit: MCPToolkit\n            if (process.env.CUSTOM_MCP_PROTOCOL === 'stdio' && serverParams!.command) toolkit = new MCPToolkit(serverParams, 'stdio')\n            else toolkit = new MCPToolkit(serverParams, 'sse')\n\n            await toolkit.initialize()\n\n            const tools = toolkit.tools ?? []\n\n            if (options.cachePool) {\n                await options.cachePool.addMCPCache(cacheKey, { toolkit, tools })\n            }\n\n            return tools as Tool[]\n        } catch (error) {","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts#L162-L198","documentation":"Thrown by CustomMCP.getTools when the internal validateMCPServerConfig(serverParams) throws, unless the env var CUSTOM_MCP_SECURITY_CHECK is set to 'false'. The validator inspects the substituted/parsed server params for forbidden shapes (e.g. disallowed command, blocked host, suspicious env values) to prevent prompt-injected configs from spawning arbitrary local processes. The original validator error message is suffixed so the offending field is identifiable.","triggerScenarios":"A server config that tries to run a blocked command (e.g. rm, curl to a private IP), an SSE url whose host is not on the allowlist, a stdio command path that is not permitted, or env values containing disallowed patterns. Can also fire on a benign config if the validator rules are stricter than expected (e.g. requiring a scheme on url).","commonSituations":"Copying a community MCP config that uses an unapproved command; an LLM auto-generating a server config that points at localhost; tightening of the validator rules in an upgrade that now rejects a previously-working config; a $vars substitution injecting a forbidden value.","solutions":["Read the suffixed validator message — it names the rejected field/rule; adjust the config to comply (allowlisted command, https url, etc.).","If the config is trusted and the rule is a false positive, set env CUSTOM_MCP_SECURITY_CHECK=false (use only in trusted/sandboxed deployments).","Audit any $vars values feeding the config — a prompt-injected variable can turn a safe config malicious.","Update to allowlisted commands/hosts rather than disabling the check globally."],"exampleFix":"// before — blocked command\n{ command:'curl', args:['http://169.254.169.254/'] }\n// after — allowlisted filesystem server\n{ command:'npx', args:['-y','@modelcontextprotocol/server-filesystem','/data'] }","handlingStrategy":"validation","validationCode":"// Pre-validate against the same rules the runtime uses, in a try block\nfunction safeValidate(config: unknown): { ok: true } | { ok: false; reason: string } {\n  try { validateMCPServerConfig(config); return { ok: true } }\n  catch (e) { return { ok: false, reason: (e as Error).message } }\n}","typeGuard":"function isAllowlistedCommand(cmd: string): boolean {\n  return ['npx','node','python','python3','uvx','docker'].includes(cmd)\n}","tryCatchPattern":"try {\n  return await getTools(nodeData, options)\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Security validation failed:')) {\n    // adjust config to satisfy validator OR set CUSTOM_MCP_SECURITY_CHECK=false in a trusted sandbox\n  }\n  throw e\n}","preventionTips":["Use allowlisted commands (npx/node/python/uvx) and https URLs in custom configs.","Audit any $vars substitution into the config for injected values.","Only set CUSTOM_MCP_SECURITY_CHECK=false in a trusted/sandboxed environment.","Re-test community configs against the validator before importing."],"tags":["mcp","security","validation","custom-mcp","sandbox"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}