CVE-2026-31226 Overview
CVE-2026-31226 is a command injection vulnerability [CWE-78] affecting the TinyZero project through commit 6652a63c57fa7e5ccde3fc9c598c7176ff15b839. The flaw resides in the HDFS file operation utilities, where the _copy() function constructs shell commands using Python f-strings and executes them via os.system(). User-controlled input, such as file paths supplied through the Hydra configuration framework, is interpolated directly into shell commands without sanitization or escaping. Attackers can inject arbitrary operating system commands to achieve remote code execution under the privileges of the user running the TinyZero training process.
Critical Impact
Unauthenticated attackers can execute arbitrary OS commands remotely, leading to full compromise of the training host and any accessible data or model artifacts.
Affected Products
- TinyZero project (open-source reinforcement learning training framework)
- All revisions up to and including commit 6652a63c57fa7e5ccde3fc9c598c7176ff15b839
- Deployments using the HDFS file operation utilities with Hydra-configured paths
Discovery Timeline
- 2026-05-12 - CVE-2026-31226 published to NVD
- 2026-05-13 - Last updated in NVD database
Technical Details for CVE-2026-31226
Vulnerability Analysis
The vulnerability is a classic OS command injection rooted in unsafe shell command construction. The _copy() helper function in TinyZero's HDFS utilities assembles command strings using Python f-strings that embed caller-supplied paths directly into the command text. The resulting string is then passed to os.system(), which invokes the system shell. Because shell metacharacters such as ;, &&, |, backticks, and $() are not escaped or rejected, any attacker who controls a path parameter can break out of the intended command and execute arbitrary commands.
TinyZero accepts configuration parameters through the Hydra framework. Path values supplied via CLI overrides, configuration files, or YAML composition flow into the HDFS copy operation without validation. This makes the injection point reachable from any interface that influences Hydra configuration during a training run.
Root Cause
The root cause is the combination of two unsafe patterns: building shell commands through string interpolation and executing them with a shell-invoking primitive. Neither shlex.quote() nor a subprocess call with shell=False and an argument list is used. The function trusts the caller to provide safe input, which is invalid in any environment where configuration values can be influenced externally.
Attack Vector
An attacker supplies a crafted path through the Hydra configuration framework. When TinyZero invokes _copy() with that path, the shell parses the injected metacharacters and runs attacker-chosen commands. For example, a path value containing a semicolon followed by an arbitrary command appends that command to the legitimate HDFS operation. Execution occurs with the privileges of the user running training, which in shared GPU clusters often includes broad access to datasets, checkpoints, and credentials.
No verified public proof-of-concept code is available. Refer to the GitHub TinyZero repository for the source code containing the affected utility.
Detection Methods for CVE-2026-31226
Indicators of Compromise
- Unexpected child processes spawned by Python training jobs, particularly shells (sh, bash) invoked by the TinyZero process tree
- Hydra configuration values or override strings containing shell metacharacters such as ;, |, &&, $(), or backticks in path fields
- Outbound network connections from training hosts to unfamiliar destinations during HDFS copy operations
- New cron jobs, SSH keys, or persistence artifacts on training nodes following a Hydra-driven job submission
Detection Strategies
- Audit Python process telemetry for os.system() invocations originating from TinyZero modules and correlate command-line content with HDFS path arguments
- Monitor for shell processes whose parent is a Python interpreter running TinyZero training scripts
- Inspect Hydra configuration logs and job submission records for path parameters containing shell control characters
- Apply behavioral identification rules that flag training workloads executing non-training binaries such as curl, wget, nc, or chmod
Monitoring Recommendations
- Forward host process telemetry and command-line arguments from training clusters into a centralized analytics platform for retrospective hunting
- Alert on any execution of system shells under the user account that runs TinyZero training jobs
- Track file integrity on shared dataset and checkpoint directories to detect tampering following a suspected injection
How to Mitigate CVE-2026-31226
Immediate Actions Required
- Stop running TinyZero training jobs that accept externally influenced path parameters until the code is patched
- Restrict who can submit or modify Hydra configurations and overrides for TinyZero workloads
- Run training processes under a dedicated, least-privileged service account with no write access to sensitive credentials or shared infrastructure
- Review recent job submissions and host telemetry for evidence of exploitation attempts
Patch Information
No official patch is referenced in the NVD entry at the time of publication. Maintainers should replace os.system() with subprocess.run() using an argument list and shell=False, or apply shlex.quote() to any user-controlled segments. Track upstream remediation in the TinyZero GitHub repository. Additional analysis is available in the Notion CVE Analysis.
Workarounds
- Wrap any local fork of the _copy() function so that path arguments are validated against a strict allowlist of characters before use
- Replace shell-invoking calls with subprocess.run([...], shell=False) and an explicit argument list
- Execute training jobs inside hardened containers with read-only filesystems and egress network restrictions to limit post-exploitation impact
- Disable Hydra command-line overrides on production training launchers and load configurations only from version-controlled files
# Configuration example: run TinyZero in a least-privileged, network-restricted container
docker run --rm \
--user 10001:10001 \
--read-only \
--cap-drop=ALL \
--network=none \
-v /data/tinyzero:/workspace:ro \
tinyzero:patched \
python train.py +data.path=/workspace/dataset
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

