Flowise and Upsonic MCP Hardening Bypass: When the Allowlist Is Not Enough
Both Flowise and Upsonic knew MCP STDIO was dangerous and built defences: command allowlists that restricted execution to trusted binaries like <code>npm</code>, <code>npx</code>, and <code>python</code>. OX Security bypassed both in under a minute by passing <code>npx -c <command></code>. The binary is on the allowlist; the argument that turns it into an arbitrary shell executor is not. The finding is a case study in why surface-level allowlists fail against the MCP STDIO execution model, and why the fix required filtering not just command names but every flag that enables inline execution.
What happened
The second exploitation family in the OX Security MCP advisory covers a class the researchers call unauthenticated command injection with hardening bypass. The scenario: a vendor knows MCP STDIO configuration accepts arbitrary command strings, recognises the risk, and implements an allowlist. Only python, npm, npx, and a few other trusted runtimes are accepted. The thinking is sound. The implementation is not.
OX demonstrated the bypass against both Upsonic 0.71.6 (CVE-2026-30625) and Flowise (GHSA-c9gw-hvqq-f33r). The trick: shift the payload from the command field to the args field. Pass npx as the command and -c <arbitrary_shell_command> as the argument. The runtime is on the allowlist. The argument flag that turns it into a shell executor is not blocked. The OS runs the arbitrary command with the privileges of the Upsonic or Flowise process.
The same bypass applies to python -c and node -e. Any interpreted runtime that accepts an inline execution flag via arguments is a bypass vector for an allowlist that only gates on the binary name. Flowise and Upsonic both required follow-up patches that filter not just the executable but also dangerous flags. Upsonic 0.72.0 added a warning to users about STDIO execution; subsequent patches hardened the argument filtering. OX published a dedicated write-up on April 27, 2026 explaining what it takes to implement argument-level controls that actually hold.
The underlying lesson is blunt: writing a robust shell argument parser is a losing battle. Every edge case you close opens a new one via a different runtime flag, a different quoting syntax, or a different interpreter that happens to be on the allowlist.
The PolicyLayer angle
The Flowise and Upsonic teams did the right thing in principle: they identified the risk and attempted mitigation. The failure was treating a binary-name allowlist as a solved problem when the actual attack surface is the entire argument space of any allowed interpreter. A policy layer that enforces at the execution primitive rather than the configuration layer solves this class of problem structurally.
The specific controls that break the bypass: restrict MCP STDIO execution to pre-approved, hash-pinned scripts rather than accepting runtime commands and argument lists; block any argument pattern that enables inline code execution (the flags -c, -e, --eval, and equivalent for all allowed runtimes); and require that the full command-plus-arguments tuple be pre-approved as a unit rather than validating the binary and the arguments independently. None of these depend on keeping an allowlist of safe flag patterns current, because they do not allow flags at all.
The policy principle here: when the attack surface is shell argument injection, argument-level filtering is a better allowlist target than binary-name filtering, but the best target is removing the shell execution path entirely in favour of parameterised subprocess calls with no inline execution capability.
Mitigations
Upgrade Upsonic to 0.72.0 or later. For Flowise, apply the patch referenced in GHSA-c9gw-hvqq-f33r. In both cases, review whether your deployment permits end users to supply MCP server configurations; if so, restrict that surface to administrators only. For any MCP deployment that must accept STDIO server definitions, enforce argument-level filtering: block -c, -e, --eval, and equivalent inline-execution flags for every allowed runtime, not just the binary name. Consider running MCP STDIO subprocesses in a restricted OS user context that cannot access sensitive credentials or network resources.
FAQs
Yes, with caveats. Upsonic 0.72.0 added a user-facing warning about STDIO execution risks and subsequent versions hardened argument filtering. Flowise patched the specific bypass vector described in GHSA-c9gw-hvqq-f33r. Neither patch addresses the root cause, which is the MCP SDK's willingness to accept arbitrary command strings; both patches add server-side controls on top of that behaviour.
No, not when the allowed binaries include runtimes that accept inline execution flags. npx -c, python -c, node -e, and equivalent flags turn any allowed interpreter into an arbitrary command executor. An allowlist that gates only on the binary name while permitting arbitrary arguments is bypassed by shifting the payload into the argument space, which is exactly what OX demonstrated.
The Flowise and Upsonic bypass is a distinct attack class. The primary OX disclosure documents unauthenticated injection where no hardening exists at all. This family is specifically about vendors who attempted a mitigation, implemented it at the wrong layer, and had that mitigation bypassed. It merits separate analysis because the fix strategy is different: you cannot patch your way to safety with a binary-name allowlist against this attack class.
References
- Flowise (CVE-2026-40933) and Upsonic (CVE-2026-30625): What to do when best practice isn't enough↗
- MCP Supply Chain Advisory: RCE Vulnerabilities Across the AI Ecosystem↗
- MCP 'design flaw' puts 200k servers at risk: Researcher↗
- Critical Anthropic MCP Vulnerability Enables Remote Code Execution Attacks↗