CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-4j8x-x6v7-w9rq: Flowise: RCE via CSVAgent csvFile data URI base64 segment is interpolated into Python source without validation

criticalCVE-2026-69264
Summary Flowise's CSVAgent interpolates an attacker-controlled segment of the csvFile data URI directly into a Python source-code template that is then executed by Pyodide. Because Pyodide is loaded with the default js bridge to globalThis (which on Node.js exposes eval and dynamic import()), the attacker can break out of the Python string literal, hand a JS string to js.eval, dynamically import any Node built-in module (fs, child_process, …), and execute arbitrary file I/O or OS commands as the Flowise process. The two validator paths around this code (validatePythonCodeForDataFrame and validateCustomReadCSVFunction) are never applied to the bootstrap template. A workspace user with chatflows:create (or any agentflows/chatflows update permission) plants a CSV Agent node with a crafted csvFile. Once the chatflow is exposed via the (whitelisted, public) POST /api/v1/prediction/:id endpoint, *any unauthenticated* request triggers the host RCE. Details Vulnerable file: packages/components/nodes/agents/CSVAgent/CSVAgent.ts The run() method extracts the file segment from the data URI by splitting on , and using two pop() calls (lines 127–138): } else { if (csvFileBase64.startsWith('[') && csvFileBase64.endsWith(']')) { files = JSON.parse(csvFileBase64) } else { files = [csvFileBase64] } for (const file of files) { if (!file) continue const splitDataURI = file.split(',') splitDataURI.pop() // discards trailing filename segment base64String += splitDataURI.pop() ?? '' // captures the segment we attack } } The captured base64String is then interpolated verbatim into a Python source string at lines 156–171: const code = `import pandas as pd import base64 from io import StringIO import json base64_string = "${base64String}" // ← line 161: interpolation sink decoded_data = base64.b64decode(base64_string) csv_data = StringIO(decoded_data.decode('utf-8')) df = pd.${customReadCSVFunc} my_dict = df.dtypes.astype(str).to_dict() print(my_dict) json.dumps(my_dict)` datafra

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
critical
Published
2026-08-04
Last updated
2026-08-04
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-4j8x-x6v7-w9rq

Referenced CVEs

CVECSIRTS overviewExternal
CVE-2026-69264coverage & exploitation statusNVD · CVE.org

Same CVEs, other sources

How other CERTs, PSIRTs and databases cover the vulnerabilities in this advisory.

More from GitHub Security Advisories