Flowise RCE Exploited by the Greeter Framework (CVE-2024-58351)
Flowise before 2.1.4 lets overrideConfig replace the JavaScript of a Custom JS Function node; the Greeter framework exploited it, and 2.1.4 fixes it.
TL;DR
- CVE-2024-58351 lets a prediction request replace the JavaScript of a Flowise Custom JS Function node, and the server runs that code. The flaw is a missing allow-list on the
overrideConfigrequest field. - Every Flowise release before 2.1.4 is affected. Era counted 4,372 internet-facing Flowise instances, and 703 of the 3,277 whose version it read had no authentication.
- VulnCheck rates the flaw CVSS v3.1 9.8 Critical. Greeter exploited it on honeypots from July to October 2026, and VulnCheck KEV lists it. CISA's KEV catalog does not list it as of November 8, 2026.
- Upgrade to 2.1.4 or later, preferably to 3.1.4, which also carries the 2026 hardening of the same code path. See "How do I fix it?".
Am I affected?
You are affected if you run a Flowise release before 2.1.4 and untrusted users can reach its prediction API. All of these conditions must hold:
- You run Flowise before 2.1.4, from the npm package
flowise, an official Docker image or a product that bundles it. - The prediction endpoint
POST /api/v1/prediction/<chatflow-id>is reachable by untrusted users, either directly or through an embedded chat widget. - A chatflow those users can reach contains a Custom JS Function node, or they can create one because app-level authentication is off.
App-level authentication in the affected 1.x and 2.0.x releases is the FLOWISE_USERNAME and FLOWISE_PASSWORD pair, and it is disabled when both variables are unset. Era's honeypots ran Flowise 1.8.2 with both variables undefined, and the recorded attacks used a chatflow with a Custom JS Function node.
The unauthenticated case is common in the exposed population. Era's census found 4,372 Flowise instances on the internet and read a version from 3,277. Of those, 703 had no authentication, and 46 of the 703 matched the vulnerable setup it had recreated.
| Branch | Affected versions | Fixed version |
|---|---|---|
| 1.x | every release | 2.1.4 (2024-11-13) |
| 2.0.x | every release | 2.1.4 (2024-11-13) |
| 2.1.x | 2.1.0 through 2.1.3 | 2.1.4 (2024-11-13) |
| 2.1.4 and later | not affected by CVE-2024-58351 | run 3.1.4 or later for the 2026 hardening |
Check the package version on every install, including containers and copies bundled inside another product:
# Global npm install
npm ls -g flowise
# Project install
npm ls flowise
# Docker: read the version inside the running container
docker exec <container> cat /usr/local/lib/node_modules/flowise/package.json | grep '"version"'
# Running instance
curl -s http://localhost:3000/api/v1/version
The version endpoint reads the nearest package.json on the server, so it reports the package the process is actually running. A container image tag is not enough when the image was built from an older package.
How do I fix it?
Upgrade to 2.1.4 or later, and use the current 3.1.4 release because it includes two later hardening commits to the same function. Then confirm that configuration override is off for every chatflow.
- Upgrade the package. For a global install, run
npm install -g flowise@3.1.4. For a project install, runnpm install flowise@3.1.4. For Docker, pull the currentflowiseai/flowiseimage and recreate the container, keeping its data volume. - Open each chatflow and check Settings, then Configuration, then the Security tab. Override config is disabled by default after 2.1.4. Enable only the node parameters that must be overridable, because the allow-list is stored per chatflow and per node type.
- Put authentication in front of the instance. Set
FLOWISE_USERNAMEandFLOWISE_PASSWORDon the affected lines, or create the admin account on 3.x, and restrict the prediction API to the networks that need it. - If you cannot upgrade yet, block
POST /api/v1/predictionfor untrusted clients at the reverse proxy. Disable public chatflows, and remove Custom JS Function nodes from any flow those clients can reach. These steps remove the entry points; they do not fix the code.
The workaround has limits. Authentication alone does not remove the flaw. Any account that can create a chatflow can add a Custom JS Function node. On the affected 1.x and 2.0.x lines, app authentication is a single administrator account. A leaked administrator password is therefore enough, which is why the upgrade is the fix and the proxy block is temporary.
What is the root cause?
The prediction API treats a request field as trusted configuration, and that configuration can replace executable code. Flowise chatflows are graphs of nodes, and the Custom JS Function node has an input named javascriptFunction whose value is JavaScript source. Before 2.1.4, the request body's overrideConfig was applied to every node input with no allow-list. This code is quoted from packages/server/src/utils/index.ts at Flowise 2.1.3:
export const replaceInputsWithConfig = (flowNodeData: INodeData, overrideConfig: ICommonObject) => {
const types = 'inputs'
const getParamValues = (inputsObj: ICommonObject) => {
for (const config in overrideConfig) {
// If overrideConfig[key] is object
if (overrideConfig[config] && typeof overrideConfig[config] === 'object') {
const nodeIds = Object.keys(overrideConfig[config])
if (nodeIds.includes(flowNodeData.id)) {
inputsObj[config] = overrideConfig[config][flowNodeData.id]
continue
} else if (nodeIds.some((nodeId) => nodeId.includes(flowNodeData.name))) {
/*
* "systemMessagePrompt": {
* "chatPromptTemplate_0": "You are an assistant" <---- continue for loop if current node is chatPromptTemplate_1
* }
*/
continue
}
}
let paramValue = inputsObj[config]
const overrideConfigValue = overrideConfig[config]
if (overrideConfigValue) {
if (typeof overrideConfigValue === 'object') {
switch (typeof paramValue) {
case 'string':
if (paramValue.startsWith('{') && paramValue.endsWith('}')) {
try {
paramValue = Object.assign({}, JSON.parse(paramValue), overrideConfigValue)
break
} catch (e) {
// ignore
}
}
paramValue = overrideConfigValue
break
case 'object':
paramValue = Object.assign({}, paramValue, overrideConfigValue)
break
default:
paramValue = overrideConfigValue
break
}
} else {
paramValue = overrideConfigValue
}
}
// Check if boolean
if (paramValue === 'true') paramValue = true
else if (paramValue === 'false') paramValue = false
inputsObj[config] = paramValue
}
}
const inputsObj = flowNodeData[types] ?? {}
getParamValues(inputsObj)
return flowNodeData
}
The loop reads every key the caller sends. When the key is javascriptFunction, the assignment at the end replaces the node's JavaScript with the caller's string. The flow is built from the stored chatflow, the override is applied to the node data in memory, and the node then initializes with the attacker's code. Nothing is written back to the chatflow, which is why the stored definition can look harmless.
The Custom JS Function node wraps that string in an async function and runs it in a vm2 NodeVM, quoted from the node's source at Flowise 1.8.2:
const nodeVMOptions = {
console: 'inherit',
sandbox,
require: {
external: { modules: deps },
builtin: builtinDeps
}
} as any
const vm = new NodeVM(nodeVMOptions)
const response = await vm.run(`module.exports = async function() {${javascriptFunction}}()`, __dirname)
The built-in allow-list covers modules such as http, net and path, not child_process. The vendor advisory lists sandbox escape as an impact of the feature. Era's reconstruction shows the payload running shell commands through child_process.execSync(). vm2 is not a security boundary against hostile JavaScript. Its own maintainers discontinued it in 2023 because escapes kept appearing.
How is it exploited?
An attacker sends the exploit as a normal prediction request, so the stored chatflow never has to contain the malicious code. The request body carries a benign question and an overrideConfig object whose javascriptFunction key holds the stage to run:
{
"question": "hello",
"overrideConfig": {
"javascriptFunction": "<JavaScript that returns the command output>"
}
}
The steps, as Era reconstructed them from the honeypot traffic:
- Reach the instance and, when app authentication is off, use or create a chatflow that contains a Custom JS Function node. The framework's flow was named
ghsa-5cph-wvm9-45gj-poc. - Send
POST /api/v1/prediction/<chatflow-id>with this request body, usinghelloas the question. - The server applies the override to the node's
javascriptFunctioninput before the node initializes. - The node runs the caller's JavaScript in the vm2 sandbox. The stage escapes the sandbox and reaches
child_process.execSync(). - The command output comes back in the prediction response. The framework sends the next command about 3.5 seconds later, again as
hello, and repeats the cycle. - Later stages enumerate the host, read environment variables and credential files, query cloud metadata, check for the Docker socket, and prepare persistence and memory-only payloads.
Era counted 4,972 of these messages over two and a half months, from July to October 2026, against seven Flowise 1.8.2 honeypots in four regions. The source address it recorded was the TOR exit node 185.246.188[.]74.
The fix had been available since November 2024, 20 months before the campaign began. The gap is the story: deployments that never applied the 2.1.4 update remained exploitable throughout.
How does the attack flow?
A single prediction request carries the attacker's JavaScript, and the server substitutes it into the node without an allow-list. The code then escapes the sandbox and runs commands as the Flowise user.
with overrideConfig.javascriptFunction"] --> B["replaceInputsWithConfig applies
the override to the node input
no allow-list"] B --> C["Custom JS Function node
runs the caller's JavaScript
inside vm2"] C --> D["vm2 sandbox escape"] D --> E["child_process.execSync
runs as the Flowise user"] E --> F["Recon, .env and SSH keys,
cloud metadata credentials"] F --> G["Persistence and memory-only
payload staging"]
What can an attacker do?
An attacker who reaches the prediction API runs commands as the Flowise process user and can read every secret that process can reach. Era's honeypot evidence shows:
- Command execution as the service account. In Era's honeypot the process ran as root with unrestricted sudo, which is a deployment choice, not a property of the flaw.
- Host reconnaissance: identity, kernel, distribution, processes, listening ports, routes, environment, container identifiers and Linux capabilities.
- Credential discovery:
.envfiles, SSH private keys andauthorized_keys, TLS client certificates, SQL and SQLite files, and the Flowise encryption key at/root/.flowise/encryption.key. - Cloud credential theft through the instance metadata service, followed by whatever the workload's cloud identity is allowed to do.
- Use of a mounted Docker socket, which can lead to control of the host and of other containers.
- Persistence through cron and systemd units, and staging of payloads that run from memory through
memfd_create().
The conditions are those in "Am I affected?". The impact after that depends on the process user, the mounted volumes, the Docker socket and the cloud identity attached to the workload.
No successful compromise of a production Flowise deployment is published in Era's report. The exploitation evidence comes from its honeypots.
Why does the fix work?
The fix makes every override opt-in per chatflow and per node parameter, so a request can no longer replace javascriptFunction unless the operator enabled it. Flowise 2.1.4 adds getAPIOverrideConfig(), which reads the chatflow's API configuration:
export const getAPIOverrideConfig = (chatflow: IChatFlow) => {
try {
const apiConfig = chatflow.apiConfig ? JSON.parse(chatflow.apiConfig) : {}
const nodeOverrides = apiConfig.overrideConfig && apiConfig.overrideConfig.nodes ? apiConfig.overrideConfig.nodes : {}
const variableOverrides = apiConfig.overrideConfig && apiConfig.overrideConfig.variables ? apiConfig.overrideConfig.variables : []
const apiOverrideStatus = apiConfig.overrideConfig && apiConfig.overrideConfig.status ? apiConfig.overrideConfig.status : false
return { nodeOverrides, variableOverrides, apiOverrideStatus }
} catch (error) {
return { nodeOverrides: {}, variableOverrides: [], apiOverrideStatus: false }
}
}
replaceInputsWithConfig() now takes the per-node allow-list and checks it before writing any input:
const isParameterEnabled = (nodeType: string, paramName: string): boolean => {
if (!nodeOverrides[nodeType]) return false
const parameter = nodeOverrides[nodeType].find((param: any) => param.name === paramName)
return parameter?.enabled ?? false
}
// ...
if (!isParameterEnabled(flowNodeData.label, config)) {
continue
}
An override now needs two opt-ins: overrideConfig.status must be true on the chatflow, and the node type must list the parameter as enabled. The default is false, and javascriptFunction is not on the list unless an operator adds it. The same guard is applied in the prediction, agent-graph and upsert paths.
The first allow-list was not the end of the story. Commit c8282c97fb (2026-02-06) removed a FILE-STORAGE:: exception that let a value skip the enable check. It also added NODE_OPTIONS to the environment variables the MCP tool refuses. Commit 23b997ee5e (2026-05-07) stopped spreading the raw overrideConfig object into the flow data, which had left a second path for caller-controlled keys. Flowise 3.1.4, published 2026-07-29, contains both, which is why it is the release to run.
How do I check if I was compromised?
Search the Flowise request logs and the host for the framework's markers; the campaign leaves distinctive strings even though its chat messages read only hello. Era published these indicators:
- Prediction requests whose JSON body contains
overrideConfigandjavascriptFunction. - A chatflow named
ghsa-5cph-wvm9-45gj-poc. - Chat messages containing
VP_DOCKER,VP_MEMFD,VP_W_OKorVP_INIT_OK, beacon replies matchingvp-alive-[0-9a-f]{8}, and exit reports matching__VP_EXIT_[0-9]+. - Process names
polld-keeper-{8-hex}andvarrun-watcher-{8-hex}. - A cron file at
/etc/cron.d/syslog-cronrun-{8-hex}or a systemd unit at/etc/systemd/system/taskd-sysrun-{8-hex}.service. - The configuration hash
07f8464533b3446e918feff1ea14c4ae, shared by the two persistence components. - Connections from the TOR exit node
185.246.188[.]74.
Run these checks on the Flowise host and on any host whose Docker socket the container can reach:
# Flowise request logs (Docker example; adjust the container name)
docker logs <container> 2>&1 | grep -Ei 'overrideConfig|javascriptFunction|ghsa-5cph-wvm9-45gj'
# Persistence artifacts
sudo find /etc/cron.d /etc/systemd/system -maxdepth 1 \( -name 'syslog-cronrun-*' -o -name 'taskd-sysrun-*.service' \)
# Framework processes
ps -eo pid,user,args | grep -E 'polld-keeper-|varrun-watcher-'
A hit is a lead, not proof. Flowise itself uses overrideConfig in its documentation and SDKs, so a request that mentions the field may be legitimate. The combination of the field with javascriptFunction, or with the chatflow name and the VP_ markers, is the stronger signal. Era's evidence comes from honeypots; no production victim's indicators are published.
Timeline
- 2024-11-13: Flowise 2.1.4 is published with the per-chatflow override allow-list.
- 2024-11-21: The Flowise advisory GHSA-5cph-wvm9-45gj is published, rating the issue High with a CVSS v4.0 score of 8.6.
- 2026-02-06: Commit
c8282c97fbremoves aFILE-STORAGE::bypass of the allow-list. - 2026-05-07: Commit
23b997ee5estops spreading the rawoverrideConfigobject into the flow data. - 2026-06-20: VulnCheck publishes CVE-2024-58351 with a CVSS v3.1 score of 9.8.
- 2026-11-03: Era publishes its analysis of the Greeter framework, whose honeypots recorded 4,972 prediction requests from July to October 2026.
- 2026-11-08: This post is published.
FAQ
Is Flowise 2.1.4 enough?
Yes for CVE-2024-58351, because 2.1.4 adds the allow-list that the flaw bypasses. Run 3.1.4 or later anyway, because two 2026 commits closed bypasses in the first allow-list and removed a second path for caller-controlled keys.
Does authentication stop the attack?
Not by itself. Authentication removes the unauthenticated case, but any account that can create a chatflow can add a Custom JS Function node and send the override. On the affected 1.x and 2.0.x lines app authentication is a single administrator account, so one leaked password is enough.
Do I need a Custom JS Function node in the chatflow?
Yes. The override replaces the value of an input, and javascriptFunction is the Custom JS Function node's input. An unauthenticated attacker can create a flow with that node; the flow observed in Era's honeypot was named ghsa-5cph-wvm9-45gj-poc.
Was this exploited against real organizations?
Era observed the Greeter framework against its own honeypots, not against named victims. It also found 4,372 internet-facing Flowise instances and 46 unauthenticated ones that matched the vulnerable setup it had recreated. That is exposure evidence, not proof of compromise.
Why does Flowise rate the issue High when VulnCheck rates it Critical?
The Flowise advisory is rated High, and its CVSS v4.0 vector uses PR:H, which assumes the attacker already holds high privileges, with a score of 8.6. VulnCheck, the CVE Numbering Authority, uses PR:N and scores it 9.8 on CVSS v3.1 and 9.3 on CVSS v4.0. The exploitation path in this post needs only network access when app authentication is off, which matches the VulnCheck vector.
What should I do if I cannot upgrade this week?
Block POST /api/v1/prediction for untrusted clients at the reverse proxy, turn off public chatflows, and remove Custom JS Function nodes from every flow those clients can reach. Then plan the upgrade, and rotate the credentials the Flowise process can read if the host was exposed.
Find exposed Flowise instances with Ostorlab
Ostorlab's attack surface discovery inventories the internet-facing services in your estate, so you can find the exposed hosts that run Flowise and prioritize the upgrade.
References
- Flowise advisory GHSA-5cph-wvm9-45gj, published 2024-11-21, with the
overrideConfigimpact list and the 2.1.4 fix: https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-5cph-wvm9-45gj (checked November 8, 2026) - CVE-2024-58351 record, published 2026-06-20, with the CVSS v3.1 9.8 and v4.0 9.3 scores and the CISA ADP SSVC block: https://www.cve.org/CVERecord?id=CVE-2024-58351 (checked November 8, 2026)
- VulnCheck advisory, "Flowise - Remote Code Execution via overrideConfig Parameter", published 2026-06-20: https://www.vulncheck.com/advisories/flowise-remote-code-execution-via-overrideconfig-parameter (checked November 8, 2026)
- Flowise 2.1.4 fix commit, "Enable/disable variables in override configuration", 2024-11-13: https://github.com/FlowiseAI/Flowise/commit/537aa51ef8 (checked November 8, 2026)
- Flowise npm package, version 2.1.4 published 2024-11-13 and the current 3.1.4 published 2026-07-29: https://www.npmjs.com/package/flowise (checked November 8, 2026)
- Flowise commit
c8282c97fb, "Fix Paramater Override Bypass", 2026-02-06: https://github.com/FlowiseAI/Flowise/commit/c8282c97fb (checked November 8, 2026) - Flowise commit
23b997ee5e, "remove ungated overrideConfig spread", 2026-05-07: https://github.com/FlowiseAI/Flowise/commit/23b997ee5e (checked November 8, 2026) - Flowise 1.8.2 Custom JS Function node source, showing the
NodeVMwrapper: https://github.com/FlowiseAI/Flowise/blob/5e4d640ed7/packages/components/nodes/utilities/CustomFunction/CustomFunction.ts (checked November 8, 2026) - Era Security, "You Had Me at Hello: Inside The Greeter, A Chinese-Language Framework Targeting AI Infrastructure", 2026-11-03, with the attack stages, exposure counts and indicators: https://era.security/blog/greeter-flowise-ai-infrastructure-attack (checked November 8, 2026)
- Flowise documentation, "Prediction", showing the endpoint, the
overrideConfigfield and the default-off configuration override: https://docs.flowiseai.com/using-flowise/prediction (checked November 8, 2026) - Flowise documentation, "Application" authentication, showing the
FLOWISE_USERNAMEandFLOWISE_PASSWORDvariables: https://docs.flowiseai.com/configuration/authorization/app-level (checked November 8, 2026) - CISA Known Exploited Vulnerabilities catalog, checked for CVE-2024-58351: https://www.cisa.gov/known-exploited-vulnerabilities-catalog (checked November 8, 2026)