fix: validate transport type in custom MCP server config to prevent command injection#4910
fix: validate transport type in custom MCP server config to prevent command injection#4910jackieya wants to merge 1 commit into1Panel-dev:v2from
Conversation
There was a problem hiding this comment.
Pull request overview
This PR tightens security for the workflow MCP node by enforcing an allow-list of safe MCP transport types when MCP server configs are provided directly via user-supplied JSON (non-referencing path), preventing command injection via stdio transport configs.
Changes:
- Adds a transport allow-list validation (
sse,streamable_http) afterhandle_variables()in the custom MCP config code path. - Raises a clear error when an unsupported transport type is found in the resolved server config.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| for _name, _cfg in servers.items(): | ||
| if isinstance(_cfg, dict) and _cfg.get('transport') not in ('sse', 'streamable_http'): | ||
| raise ValueError( | ||
| f"Unsupported transport type: {_cfg.get('transport')}. " |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
041686c to
12f0996
Compare
… command injection
12f0996 to
352197d
Compare


fix: validate transport type in custom MCP server config
Summary
This PR adds a transport type whitelist check in the
elsebranch ofBaseMcpNode.execute()to prevent command injection viastdiotransport in custom MCP server configurations.Related: GHSA-38q2-4mm7-qf5h, GHSA-pw52-326g-r5xj
Problem
The fix in commit c8e8afa for GHSA-38q2-4mm7-qf5h only restricts the
referencingcode path. Theelsebranch — which loadsmcp_serversdirectly from user-supplied JSON — remains unrestricted. An attacker can setmcp_sourceto any non-referencingvalue (or omit it entirely, since the field is optional) to bypass the fix and inject astdiotransport configuration with arbitrarycommandandargs, achieving Remote Code Execution.Changes
File:
apps/application/flow/step_node/mcp_node/impl/base_mcp_node.pyAdded transport type validation after
handle_variables()to ensure all server configs only usesseorstreamable_httptransport. Placing the check after variable substitution prevents bypass via variable references.else: servers = json.loads(mcp_servers) servers = self.handle_variables(servers) + for _name, _cfg in servers.items(): + if isinstance(_cfg, dict) and _cfg.get('transport') not in ('sse', 'streamable_http'): + raise ValueError( + f"Unsupported transport type: {_cfg.get('transport')}. " + "Only 'sse' and 'streamable_http' are allowed." + ) params = json.loads(json.dumps(tool_params)) params = self.handle_variables(params)Why after
handle_variables()?If the check is placed before
handle_variables(), an attacker can use a variable reference (e.g.,["global", "evil_var"]) as the server config value. This bypasses theisinstance(cfg, dict)check, and thenhandle_variables()resolves it into a dict containing"transport": "stdio"— effectively bypassing the patch.Testing
Unsupported transport type: stdio✅['root\n'](RCE confirmed)sse/streamable_httpMCP workflows: unaffected ✅