VAITP Dataset

← Back to the dataset

CVE-2026-9147

uproot: Code injection via crafted ROOT file metadata allows code execution.

  • CVSS 8.5
  • CWE-94
  • Input Validation and Sanitization
  • Local

uproot dynamically generates Python class source code from ROOT TStreamerInfo records in a file and compiles it at runtime. Some file-controlled streamer metadata fields (for example, streamer element names) are interpolated into the generated Python source without safe quoting via repr() or the !r format specifier. An attacker who can supply a crafted ROOT file can place Python expression-breaking content into a streamer metadata field. When uproot generates and invokes the corresponding reader method, the injected Python expression is evaluated in the context of the process opening the file, resulting in arbitrary Python code execution in applications that open or process attacker-controlled ROOT files with affected uproot code paths.

CVSS base score
8.5
Published
2026-07-18
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
Local
Impact
Arbitrary Code Execution
Affected component
uproot
Fixed by upgrading
Yes

Solution

Upgrade `uproot` to version 4.1.9 or later, and `uproot5` to version 5.0.3 or later.

Vulnerable code sample

import os

def vulnerable_code_generator(streamer_element_name):
    # This function simulates the vulnerable behavior. It generates Python source
    # code by directly embedding a metadata string from an untrusted source.
    # THE VULNERABILITY: The 'streamer_element_name' is formatted directly
    # into the code string without being quoted or sanitized via repr().
    generated_code = f"""
class GeneratedClass:
    def __init__(self):
        # The attacker's payload is injected directly into this line.
        self.{streamer_element_name} = "some_data"

# The generated code is then executed.
instance = GeneratedClass()
"""
    # In the context of the vulnerable application, this generated code
    # would be compiled and executed.
    exec(generated_code)

# An attacker crafts a file where a metadata field contains a malicious string.
# The payload is designed to complete the previous statement, execute a new
# malicious command, and then use a comment to ignore the rest of the original line.
malicious_payload = "attribute = 1; import os; os.system('echo VULNERABILITY EXPLOITED'); #"

# The user's application unwittingly calls the vulnerable function with the
# attacker's malicious payload, believing it to be a valid element name.
vulnerable_code_generator(malicious_payload)

Patched code sample

def generate_safe_reader_line(untrusted_streamer_element_name):
    """
    Simulates the fixed code generation for a ROOT streamer element.

    The original vulnerability was that 'untrusted_streamer_element_name',
    which is read from the file, was directly formatted into a Python code
    string. An attacker could craft a name like:
    "my_var'); import os; os.system('echo pwned'); ('"
    This would break out of the string literal in the generated code and
    execute the malicious command.

    The fix is to use the '!r' format specifier (or repr()), which ensures
    the untrusted input is always treated as a single, safe string literal,
    neutralizing the injection.
    """
    # The '!r' specifier is the key to the fix. It calls repr() on the
    # variable, safely quoting it and escaping special characters.
    generated_line = f"self.data[{untrusted_streamer_element_name!r}] = read_value(chunk)"
    return generated_line

Payload

dummy_variable;__import__('os').system('id')#

Cite this entry

@misc{vaitp:cve20269147,
  title        = {{uproot: Code injection via crafted ROOT file metadata allows code execution.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-9147},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-9147/}}
}
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 ::