system: OPERATIONAL
← back to all hacks
AGENTS CRITICAL NEW

Flowise CVE-2026-41264: LLM-written pandas code that escalates to RCE

A prompt injection in Flowise's CSV Agent makes the model emit Python that escapes a regex denylist and runs OS commands. Disclosed April 15, 2026 and patched in 3.1.0.

2026-06-15 // 6 min affects: flowise, flowise-components

What is this?

CVE-2026-41264 is a remote-code-execution flaw in the CSV Agent node of Flowise, the popular open-source low-code builder for LLM apps and agents. It was reported by Dre Cura and Nicholas Zubrisky of Trend Micro’s Zero Day Initiative (ZDI-CAN-29411), published in the vendor advisory on April 15, 2026, and entered the GitHub and GitLab advisory databases on April 21. It affects flowise and flowise-components up to and including 3.0.13 and is fixed in 3.1.0. ZDI rates it 9.8 (CVSS v3.1); GitHub scores it 9.2 (CVSS v4). On the prompt-injection path, no authentication is required.

The interesting part is not that an agent runs code — that is the node’s whole job — but how the bug survives a security control that was specifically written to stop it. CVE-2026-41264 is a bypass of the fix shipped for the earlier CVE-2026-41137.

How it works

The CSV Agent answers questions about an uploaded CSV by asking the model to write pandas code, then executing that code in a Pyodide (in-process WebAssembly Python) runtime. The system prompt politely instructs the model to emit only pandas/numpy operations and to avoid import, os, subprocess, eval, and similar. That instruction is not a security boundary — it is text the model can be argued out of.

The real control is a function, validatePythonCodeForDataFrame(), that runs the model’s output through a list of forbidden regular expressions (FORBIDDEN_PATTERNS) before execution. This is a denylist, and the advisory’s classification says it all: CWE-184, Incomplete List of Disallowed Inputs. One of the patterns, /\bimport\s+(?!pandas|numpy\b)/g, tries to forbid importing anything but pandas or numpy, and another (/\bos\./g) tries to block the os module. Both fall to a single aliasing trick documented in the advisory:

# Conceptual bypass from the public ZDI advisory — patched in 3.1.0
import pandas as np, os as pandas   # 'os' is imported under the alias 'pandas'
pandas.system("[REDACTED]")         # so 'pandas.system(...)' is really os.system(...)

Because the line begins with import pandas, the import regex is satisfied; because the dangerous call is written pandas.system(...), the \bos\. pattern never matches. The model is steered into producing this through ordinary prompt-injection phrasing inside the user’s question (the {question} slot of the system prompt). The Pyodide environment is not sandboxed at the OS level, so the call executes in the context of the user running the Flowise server.

ZDI documents three exploitation routes in its proof of concept: an unauthenticated prompt injection sent to a chatflow’s prediction endpoint; an authenticated attacker who wires the CSV Agent to a malicious model server that simply returns hostile “code”; and the malicious-server primitive on its own. The PoC notes a realistic caveat for LLM bugs: because output is probabilistic, it “may take multiple attempts to be successful or require a different prompt injection technique depending on the model used” — they tested Llama 3.2 via Ollama.

Why it matters

This is the lethal trifecta pattern in its sharpest form: untrusted input (the question, and the CSV itself), a powerful capability (code execution), and a model deciding what to run. Flowise is widely deployed and frequently exposed to the internet, so a node intended to “answer questions about a spreadsheet” becomes a path to full host compromise — including any provider API keys and cloud credentials the server holds. The deeper lesson generalises far beyond Flowise: a natural-language instruction in a system prompt is not an access control, and a regex denylist over a Turing-complete language is a losing game. Python offers countless ways to reach a capability (aliasing, attribute traversal, reflection via __class__/__subclasses__), and the validator can only ever block the spellings its authors imagined.

Defenses

Don’t denylist code — sandbox the runtime. The durable fix is OS-level isolation: run untrusted, model-generated code in a separate process or container with no network, a read-only filesystem, dropped capabilities, and seccomp limits. In-process Pyodide shares the host’s reach and is not a security boundary by itself.

Prefer allowlists and non-code execution. Where feasible, don’t let the model emit free-form code at all. Constrain it to a vetted set of DataFrame operations, or have it produce a structured query that your code validates and executes — an allowlist of what is permitted rather than a denylist of what is forbidden.

Treat data files as injection vectors. The CSV contents (and column names) flow into the prompt, so untrusted spreadsheets can carry instructions just as a user message can. Validate, quote, and isolate them.

Patch and inventory. Upgrade Flowise to 3.1.0 or later, which removes the gap by disallowing all imports in the CSV Agent. Then find your exposed instances — Flowise should not sit on the public internet without authentication and network egress controls.

Least privilege for the agent host. Run Flowise as an unprivileged user, scope its API keys narrowly, and segment it from cloud metadata endpoints so a single RCE does not become a credential heist.

Status

ItemDetail
CVECVE-2026-41264 (GHSA-3hjv-c53m-58jj)
Affectedflowise, flowise-components ≤ 3.0.13
Patched3.1.0 (all imports disallowed in CSV Agent)
Severity9.8 CVSS v3.1 (ZDI) / 9.2 CVSS v4 (GitHub); CWE-184
Auth requiredNo (prompt-injection path)
Reported byDre Cura & Nicholas Zubrisky, Trend Micro ZDI
Vendor advisoryApril 15, 2026
RelationBypass of the fix for CVE-2026-41137

Sources