FlowiseAI/Flowise · error · Error

Security validation failed: ${error.message}

Error message

Security validation failed: ${error.message}

What it means

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.

Source

Thrown at packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts:180

                return cachedResult.tools
            }
        }

        try {
            let serverParams
            if (typeof mcpServerConfig === 'object') {
                serverParams = substituteVariablesInObject(mcpServerConfig, sandbox)
            } else if (typeof mcpServerConfig === 'string') {
                const substitutedString = substituteVariablesInString(mcpServerConfig, sandbox)
                const serverParamsString = convertToValidJSONString(substitutedString)
                serverParams = JSON.parse(serverParamsString)
            }

            if (process.env.CUSTOM_MCP_SECURITY_CHECK !== 'false') {
                try {
                    validateMCPServerConfig(serverParams)
                } catch (error) {
                    throw new Error(`Security validation failed: ${error.message}`)
                }
            }

            // Compatible with stdio and SSE
            let toolkit: MCPToolkit
            if (process.env.CUSTOM_MCP_PROTOCOL === 'stdio' && serverParams!.command) toolkit = new MCPToolkit(serverParams, 'stdio')
            else toolkit = new MCPToolkit(serverParams, 'sse')

            await toolkit.initialize()

            const tools = toolkit.tools ?? []

            if (options.cachePool) {
                await options.cachePool.addMCPCache(cacheKey, { toolkit, tools })
            }

            return tools as Tool[]
        } catch (error) {

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Read the suffixed validator message — it names the rejected field/rule; adjust the config to comply (allowlisted command, https url, etc.).
  2. 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).
  3. Audit any $vars values feeding the config — a prompt-injected variable can turn a safe config malicious.
  4. Update to allowlisted commands/hosts rather than disabling the check globally.

Example fix

// before — blocked command
{ command:'curl', args:['http://169.254.169.254/'] }
// after — allowlisted filesystem server
{ command:'npx', args:['-y','@modelcontextprotocol/server-filesystem','/data'] }
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate against the same rules the runtime uses, in a try block
function safeValidate(config: unknown): { ok: true } | { ok: false; reason: string } {
  try { validateMCPServerConfig(config); return { ok: true } }
  catch (e) { return { ok: false, reason: (e as Error).message } }
}

Type guard

function isAllowlistedCommand(cmd: string): boolean {
  return ['npx','node','python','python3','uvx','docker'].includes(cmd)
}

Try / catch

try {
  return await getTools(nodeData, options)
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Security validation failed:')) {
    // adjust config to satisfy validator OR set CUSTOM_MCP_SECURITY_CHECK=false in a trusted sandbox
  }
  throw e
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12). Data as JSON: /api/errors/1177cc5b92f481f4. Report an issue: GitHub.