What Type of Bypass Is Exploited in flowise-mcp-env-case-bypass-poc?
The PoC exploits a case‑variant environment variable bypass in Flowise's Custom MCP component, where lowercase variants like node_options slip past a case‑sensitive denylist and achieve RCE on Windows.
The flowise-mcp-env-case-bypass-poc repository in bikini/exploitarium demonstrates how a subtle validation flaw in Flowise 3.1.2's Model Context Protocol (MCP) implementation allows attackers to bypass security controls using case‑insensitive environment variable naming on Windows. This vulnerability exposes the importance of platform‑aware input normalization in Node.js applications that spawn child processes.
The Core Vulnerability: Case‑Sensitive Validation on a Case‑Insensitive Platform
Flowise's Custom MCP node attempts to block dangerous environment variables through a denylist approach. The vulnerability resides in how this validation handles environment variable names.
In packages/components/nodes/tools/MCP/core.ts, the validateEnvironmentVariables function performs an exact‑case string comparison against a hardcoded list of dangerous variables:
// packages/components/nodes/tools/MCP/core.ts
const dangerousEnvVars = ['PATH', 'LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'NODE_OPTIONS']
for (const [key, value] of Object.entries(env)) {
// Exact‑case comparison – fails on Windows when key is lower‑cased
if (dangerousEnvVars.includes(key)) {
throw new Error(`Forbidden environment variable: ${key}`)
}
}
This approach works correctly on Linux and macOS, where environment variable names are case‑sensitive. However, Windows treats environment variable names as case‑insensitive, meaning NODE_OPTIONS, node_options, and Node_Options all resolve to the same variable.
How the Case‑Variant Bypass Works
The attack chain follows three steps:
- Attacker submits lowercase variant – Instead of
NODE_OPTIONS(blocked), supplynode_options - Validation passes – The exact‑case check
dangerousEnvVars.includes('node_options')returnsfalse - Child process honors the variable – Windows normalizes the name, Node.js receives the options, and arbitrary code executes
The PoC demonstrates this by launching a Node.js process with node_options=--require loader.js, where loader.js contains attacker‑controlled code.
PoC Implementation
The Python driver in poc.py reproduces the bypass:
# flowise-mcp-env-case-bypass-poc/poc.py
import subprocess, json, argparse, pathlib
parser = argparse.ArgumentParser()
parser.add_argument('--marker', default='C:\\Temp\\flowise_marker.txt')
args = parser.parse_args()
env = {"node_options": "--require loader.js"} # lower‑case bypass
subprocess.run(["node", "canary.js"], env=env)
result = {
"flowise_style_lower_variant_accepted": pathlib.Path(args.marker).exists()
}
print(json.dumps(result, indent=2))
Execution confirms the bypass:
python poc.py
Successful exploitation creates the marker file, proving that node_options was accepted despite NODE_OPTIONS being on the denylist.
Impact: From Bypass to Arbitrary Code Execution
The flowise-mcp-env-case-bypass-poc vulnerability enables Remote Code Execution (RCE) in Flowise worker contexts. Here's why:
NODE_OPTIONScontrols Node.js runtime behavior- The
--requireflag loads arbitrary modules before execution - Combined with case‑variant bypass, attackers can inject malicious loaders
- The MCP stdio connection in
CustomMCP.tspropagates these environment variables to spawned processes
This represents a high‑severity bypass because it defeats a security control specifically designed to prevent code injection through environment manipulation.
The Fix: Case‑Normalization Before Comparison
The remediated validation normalizes keys to uppercase before comparison:
const dangerousEnvVars = ['PATH', 'LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'NODE_OPTIONS']
for (const [key, value] of Object.entries(env)) {
// Normalize to upper‑case before comparison – works on Windows too
if (dangerousEnvVars.includes(key.toUpperCase())) {
throw new Error(`Forbidden environment variable: ${key}`)
}
}
This approach accounts for Windows case‑insensitivity while maintaining security across all platforms.
Alternative Mitigation Strategies
Beyond case‑normalization, consider these defenses:
- Allow‑list approach – Explicitly permit only required environment variables rather than blocking known‑dangerous ones
- Platform‑aware validation – Detect the operating system and apply appropriate normalization rules
- Schema‑based validation – Validate MCP configuration against strict schemas before processing
- Sandboxed execution – Isolate MCP worker processes with restricted environment inheritance
Summary
- Bypass type: Case‑variant environment variable bypass exploiting Windows case‑insensitivity
- Root cause: Exact‑case string comparison in
validateEnvironmentVariablesatpackages/components/nodes/tools/MCP/core.ts - Attack vector: Lower‑cased
node_optionsbypassesNODE_OPTIONSdenylist, enabling--requireinjection - Impact: Arbitrary code execution in Flowise MCP worker context
- Fix: Normalize environment variable names to uppercase before denylist comparison
Frequently Asked Questions
What makes the flowise-mcp-env-case-bypass-poc vulnerability possible on Windows specifically?
Windows handles environment variable names as case‑insensitive at the OS level, while the Flowise validation logic assumes case‑sensitive matching. This platform difference creates a semantic gap where node_options passes validation but resolves to the same variable as NODE_OPTIONS when interpreted by the Node.js runtime.
Why doesn't this bypass work on Linux or macOS?
Linux and macOS use case‑sensitive environment variable handling, so node_options and NODE_OPTIONS are treated as distinct variables. A Node.js process on these platforms would not recognize node_options as controlling runtime options, rendering the bypass ineffective.
What Flowise version is vulnerable to this case‑variant bypass?
The PoC targets Flowise 3.1.2 (flowise-components@3.1.2) specifically. The vulnerable code resides in the Custom MCP stdio node implementation, which processes environment variable configuration through the validateEnvironmentVariables function in core.ts.
How can developers prevent similar case‑variant bypasses?
Always normalize environment variable names against the platform's case‑handling semantics before security checks. For cross‑platform Node.js code, convert keys to a consistent case (typically uppercase) or use platform detection to apply appropriate validation rules. Prefer allow‑list validation over denylist approaches when feasible.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →