# What Type of Bypass Is Exploited in flowise-mcp-env-case-bypass-poc?

> Discover the case variant environment variable bypass in Flowise's Custom MCP component. Learn how lowercase variants achieve RCE on Windows in this PoC exploit.

- Repository: [bikini/exploitarium](https://github.com/bikini/exploitarium)
- Tags: deep-dive
- Published: 2026-09-06

---

**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`](https://github.com/bikini/exploitarium/blob/main/packages/components/nodes/tools/MCP/core.ts), the `validateEnvironmentVariables` function performs an **exact‑case string comparison** against a hardcoded list of dangerous variables:

```typescript
// 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:

1. **Attacker submits lowercase variant** – Instead of `NODE_OPTIONS` (blocked), supply `node_options`
2. **Validation passes** – The exact‑case check `dangerousEnvVars.includes('node_options')` returns `false`
3. **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`](https://github.com/bikini/exploitarium/blob/main/loader.js) contains attacker‑controlled code.

### PoC Implementation

The Python driver in [`poc.py`](https://github.com/bikini/exploitarium/blob/main/poc.py) reproduces the bypass:

```python

# 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:

```powershell
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_OPTIONS` controls Node.js runtime behavior
- The `--require` flag loads arbitrary modules before execution
- Combined with case‑variant bypass, attackers can inject malicious loaders
- The MCP stdio connection in [`CustomMCP.ts`](https://github.com/bikini/exploitarium/blob/main/CustomMCP.ts) propagates 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:

```typescript
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 `validateEnvironmentVariables` at [`packages/components/nodes/tools/MCP/core.ts`](https://github.com/bikini/exploitarium/blob/main/packages/components/nodes/tools/MCP/core.ts)
- **Attack vector**: Lower‑cased `node_options` bypasses `NODE_OPTIONS` denylist, enabling `--require` injection
- **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`](https://github.com/bikini/exploitarium/blob/main/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.