NewApp Monitoring is liveSign up free
AgentbeamBeta
AI agent vulnerability · Flowise

CVE-2026-70477: Flowise: CSV Agent Prompt Injection Remote Code Execution Vulnerability

criticalCVSS 4.0 9.5GHSA-5xvg-pmgg-3mxr

Prompt injection against a Flowise chatflow with a CSV Agent node can make the LLM write Python that passes the blocklist and runs in Pyodide, giving code execution as the Flowise service account. Trend Micro ZDI reported it against 3.1.1; versions up to 3.1.2 are listed. Upgrade flowise and flowise-components to 3.1.3.

Published Aug 4, 2026 · Analysis Oct 25, 2026

What an attacker can do

When a user queries a CSV Agent chatflow, CSV_Agents.run reads the CSV, loads Pyodide and gets column names with pandas. It puts that dictionary and the user's question into a system prompt and sends it to the configured LLM. The reply is stored as pythonCode, checked by validatePythonCodeForDataFrame, and run with pyodide.runPythonAsync. The user question goes into the prompt unfiltered, so the user steers the code the model writes.

The checker is a static regex blocklist. ZDI showed eight bypasses. They include a @exec decorator with a concatenated __import__, chr() encoding, aliasing eval or vars to a variable, df.query() with an encoded builtin, MRO traversal with __getattribute__, generator frame inspection (gi_frame.f_globals), an exception traceback walk to f_builtins, and __build_class__.__self__. Pyodide is not isolated from the host OS in this setup, so any code that passes runs with the service account's access.

An unauthenticated attacker who can send prompts to such a chatflow can try prompt injection. ZDI notes that success depends on the model and may need several attempts. An authenticated attacker has a deterministic path: create a chatflow whose ChatOllama model points at an attacker server that answers with the payload, so the real LLM is never used. The CVSS vector reflects high attack complexity and no privileges.

Who is affected

flowise and flowise-components on npm, version 3.1.2 and earlier; ZDI tested 3.1.1 on Ubuntu. A chatflow must contain a CSV Agent node. Check the version:

npm ls flowise flowise-components

flowise

Ecosystem
npm
Affected
<= 3.1.2
Fixed in
3.1.3
Check
npm ls flowise

flowise-components

Ecosystem
npm
Affected
<= 3.1.2
Fixed in
3.1.3
Check
npm ls flowise-components

How to fix it

Upgrade both packages to 3.1.3.

npm install -g [email protected]

In pull request 6499 the maintainers removed the CSV Agent and Airtable Agent nodes, the validator pythonCodeValidator.ts and the pyodide dependency, instead of extending the blocklist. Flows using those nodes will break. The advisory lists no workaround. Meanwhile, take chatflows with a CSV Agent offline from untrusted users.

How to tell if you were hit

Review chat and prediction logs on CSV Agent chatflows for prompts that tell the model to ignore instructions or to answer in Python code, and for errors reading Sorry, I'm unable to find answer for question ... using following code, which print the code that failed. Check for chatflows whose chat model is ChatOllama pointed at an unknown host, and for outbound requests from Flowise to that host on /api/chat. On the server, look for shells or other child processes started by the Flowise Node.js process.

Original advisory

From the GitHub Advisory Database (CC BY 4.0).

-- ABSTRACT -------------------------------------

Trend Micro's Zero Day Initiative has identified a vulnerability affecting the following products: Flowise - Flowise

-- VULNERABILITY DETAILS ------------------------

  • Version tested: 3.1.1
  • Installer file: https://github.com/FlowiseAI/Flowise (npm install [email protected])
  • Platform tested: Ubuntu 25.10

---

A prompt injection sent to a chatflow using a CSV Agent node can cause the LLM to respond with a malicious Python script that bypasses the blocklist validator and executes in an unsandboxed pyodide environment. An attacker can leverage this to execute arbitrary code in the context of the user running the server.

This vulnerability allows remote attackers to execute arbitrary code on affected installations of Flowise. Authentication is not required to exploit this vulnerability.

The specific flaw exists within the run method of the CSV_Agents class. The issue results from insufficient input sanitization when using untrusted data to construct an LLM prompt. An attacker can leverage this vulnerability to execute code in the context of the service account.

Analysis

When a user makes a query against a chatflow using the CSV Agent node, the run method of the CSV_Agents class is called. This method reads the CSV file, loads a pyodide environment, and uses pandas to extract column names and data types into a dictionary. It then constructs a system prompt using that dictionary and the user's input, and sends this prompt to a configured LLM. The LLM response is stored in a variable named pythonCode. The method then attempts to validate this value using validatePythonCodeForDataFrame from packages/components/src/pythonCodeValidator.ts before evaluating it in pyodide.

The validator relies on a static regex blocklist. It can be bypassed using obfuscation techniques including string concatenation to reconstruct forbidden identifiers, chr() encoding, aliasing of dangerous builtins, __getattribute__ with concatenated attribute names, frame object inspection, MRO traversal, df.query() expression evaluation, and decorator syntax to invoke exec indirectly. Furthermore, pyodide is not sandboxed from the host operating system, so any Python code that passes the validator is executed with full access to OS interfaces.

From packages/components/nodes/agents/CSVAgent/CSVAgent.ts:

let pythonCode = ''
if (dataframeColDict) {
    const chain = new LLMChain({
        llm: model,
        prompt: PromptTemplate.fromTemplate(systemPrompt),
        verbose: process.env.DEBUG === 'true' ? true : false
    })
    const inputs = {
        dict: dataframeColDict,
        question: input // user-controlled input substituted into prompt
    }
    const res = await chain.call(inputs, [loggerHandler, ...callbacks])
    pythonCode = res?.text // LLM response assigned to pythonCode
    pythonCode = pythonCode.replace(/^```[a-z]+\n|\n```$/gm, '')
}

let finalResult = ''
if (pythonCode) {
    const validation = validatePythonCodeForDataFrame(pythonCode) // blocklist validation applied
    if (!validation.valid) {
        throw new Error(
            `Generated code was rejected for security reasons (${
                validation.reason ?? 'unsafe construct'
            }). Please rephrase your question to use only pandas DataFrame operations.`
        )
    }
    try {
        const code = `import pandas as pd\nimport numpy as np\n${pythonCode}`
        finalResult = await pyodide.runPythonAsync(code) // executed in unsandboxed pyodide
    } catch (error) {
        throw new Error(`Sorry, I'm unable to find answer for question: "${input}" using following code: "${pythonCode}"`)
    }
}

An unauthenticated attacker with the ability to send prompts to a chatflow using the CSV Agent node may use prompt injection to cause the LLM to respond with a malicious Python script. An authenticated attacker may instead configure a chatflow that points to an attacker-controlled server, which responds to LLM requests with an attacker-controlled Python payload, bypassing the LLM entirely.

Eight bypass variants were demonstrated against the validator:

| Variant | Technique | Bypasses |
| 0 | `@exec` decorator with string-concatenated `__import__` | `/\bexec\s*\(/`, `/\b__import__\s*\(/` |
| 1 | `eval` aliased to a variable, payload chr()-encoded | `/\beval\s*\(/`, `/\bimport\b/` |
| 2 | `df.query()` with chr()-encoded `@__builtins__.__import__` | `/\b__builtins__\b/`, `/\b__import__\s*\(/` |
| 3 | MRO traversal + `__getattribute__` + `__subclasses__` -> `BuiltinImporter.load_module` | `/\b__class__\b/`, `/\b__subclasses__\s*\(/`, `/\b__mro__\b/` |
| 4 | Generator frame inspection via `gi_frame.f_globals['__loader__']` | `/\b__loader__\b/`, `/\b__globals__\b/` |
| 5 | Exception traceback frame walk to `f_builtins['__import__']` | `/\b__globals__\b/`, `/\b__import__\s*\(/` |
| 6 | `__build_class__.__self__.__getattribute__('__import__')` | `/\b__import__\s*\(/` |
| 7 | `vars` aliased to a variable, `__builtins__` accessed via dict key | `/\bvars\s*\(/`, `/\b__builtins__\b/`, `/\b__import__\s*\(/` |

Repro

The proof of concept (poc.py) has three modes of operation:

mode = "server": Starts a malicious server that responds to "/api/chat" requests with a JSON object containing an LLM response with the selected attack payload.

mode = "chatflow": Authenticates to the Flowise server, creates a chatflow with a CSV Agent node configured to use a ChatOllama model pointed at the malicious server, and triggers a prediction to execute the payload.

mode = "prompt_injection": Sends a prompt injection payload directly to an existing chatflow's prediction endpoint. Due to the nature of LLM responses, it may take multiple attempts or require a different injection technique depending on the model used.

python3 poc.py --mode [server OR chatflow OR prompt_injection] [--user <USER> --passwd <PASSWORD> --host <HOST> --r_host <R_HOST> --r_port <R_PORT> --l_port <L_PORT> --port <PORT> --cmd <CMD> --attack <ATTACK> --chatflow_id <CHAT_ID>]

-- CREDIT --------------------------------------- This vulnerability was discovered by: Dre Cura (@dre_cura) of TrendAI Research

Credited to zdi-disclosures.

Questions

Is authentication needed for CVE-2026-70477?

Not for the prompt injection route. ZDI says authentication is not required if the attacker can send prompts to the chatflow. The route that skips the real LLM needs a login to create a chatflow.

Does a stronger LLM prevent this?

The advisory does not say so. ZDI notes that results vary by model and may need repeated attempts. The root issue is that generated code is run after a regex check that can be bypassed.

How many ways did ZDI bypass the validator?

Eight variants, using decorators, aliasing, chr() encoding, df.query, MRO traversal, frame inspection, traceback walking and __build_class__.

References

How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. The analysis is written by an AI model from the sources listed above and checked by automated rules before it is published. Check versions against the vendor's advisory before you act. Methodology

More Flowise vulnerabilities

All Flowise entries