CVE-2026-9147 Overview
CVE-2026-9147 is a code injection vulnerability in uproot, a Python library used by the scikit-hep scientific computing ecosystem to read ROOT files. The library dynamically generates Python class source code from TStreamerInfo records inside a ROOT file and compiles that source at runtime. File-controlled streamer metadata fields, including streamer element names, are interpolated into the generated source without safe quoting through repr() or the !r format specifier. An attacker who supplies a crafted ROOT file can inject arbitrary Python expressions that execute when uproot builds and invokes the reader method. The flaw is categorized as [CWE-94] Improper Control of Generation of Code.
Critical Impact
Opening an attacker-controlled ROOT file with an affected version of uproot results in arbitrary Python code execution in the process context of the user running the analysis.
Affected Products
- scikit-hep uproot5 (uproot) prior to the patched commit c045c28
- Python analysis workflows and Jupyter notebooks that ingest untrusted ROOT files
- Downstream high-energy physics tooling depending on vulnerable uproot releases
Discovery Timeline
- 2026-07-18 - CVE-2026-9147 published to the National Vulnerability Database
- 2026-07-23 - Last updated in NVD database
Technical Details for CVE-2026-9147
Vulnerability Analysis
uproot reads ROOT files by parsing TStreamerInfo records, which describe how objects were serialized. To decode these objects efficiently, uproot builds Python source code at runtime and compiles it into reader methods. Fields such as streamer element names are pulled from the file and inserted directly into the generated Python source as string literals or identifiers. Because the interpolation does not pass these values through repr() or use the !r format specifier, characters such as quotes, parentheses, and newlines break out of the intended string context. The generated source is then executed, causing arbitrary Python expressions supplied inside the file to run.
Root Cause
The root cause is unsafe template composition. Attacker-controlled strings from TStreamerInfo fields are concatenated into Python source without escaping. When compile() or exec() processes the generated code, injected expressions become executable statements rather than inert data.
Attack Vector
Exploitation requires a victim to open a crafted ROOT file with a vulnerable uproot version. This is a local attack vector with user interaction, typical of malicious datasets distributed through shared storage, collaboration repositories, or email attachments in scientific environments. Successful exploitation yields code execution with the privileges of the analyst opening the file.
# Security patch from src/uproot/interpretation/identify.py
# Replaces unsafe eval() with ast.literal_eval() for parsed dimensions
if getdims:
m = _title_has_dims.match(leaf.member("fTitle"))
if m is not None:
- dims = tuple(eval(m.group(2).replace("][", ", ")))
+ dims = tuple(ast.literal_eval(m.group(2).replace("][", ", ")))
if leaf.classname == "TLeafO":
return numpy.dtype((numpy.bool_, dims))
# Source: https://github.com/scikit-hep/uproot5/commit/c045c2824295d907d2e705f31110c742928e50e7
The patch replaces eval() with ast.literal_eval(), which only evaluates literals and rejects arbitrary expressions. Related fixes in the same change safely quote streamer metadata during source generation. See the GitHub Security Advisory GHSA-6946-mq52-g438 and the VulnCheck Code Injection Advisory for additional technical context.
Detection Methods for CVE-2026-9147
Indicators of Compromise
- ROOT files (.root) received from untrusted sources whose TStreamerInfo records contain quotes, parentheses, or Python keywords in element name fields.
- Python analysis processes spawning unexpected child processes such as sh, bash, curl, or python -c shortly after opening a ROOT file.
- Outbound network connections initiated by Jupyter kernels or Python interpreters immediately after uproot.open() calls.
Detection Strategies
- Inspect installed uproot versions across analysis hosts and flag builds preceding commit c045c28.
- Instrument Python environments to log calls to uproot.open, uproot.reading, and dynamic compile() or exec() invocations originating from the uproot package.
- Compare file-provided streamer names against expected ROOT class naming conventions and alert on non-identifier characters.
Monitoring Recommendations
- Monitor endpoints running scientific Python stacks for anomalous process trees originating from python, jupyter, or ipykernel parents.
- Alert on egress from research workstations following the ingestion of externally sourced ROOT files.
- Track package inventory changes to confirm that patched uproot versions are deployed across shared compute clusters.
How to Mitigate CVE-2026-9147
Immediate Actions Required
- Upgrade uproot to the release containing commit c045c2824295d907d2e705f31110c742928e50e7 or later on all analysis systems.
- Treat every ROOT file received from external collaborators as untrusted until the fix is applied.
- Audit shared storage and dataset repositories for ROOT files introduced from unverified sources.
Patch Information
The fix is committed in the scikit-hep/uproot5 repository under commit c045c28. The patch replaces unsafe eval() usage with ast.literal_eval() and applies safe quoting to streamer metadata used in generated source. Full advisory details are published in GHSA-6946-mq52-g438.
Workarounds
- Restrict uproot execution to sandboxed environments or containers with no network egress and minimal filesystem access.
- Reject ROOT files from unauthenticated sources at ingest gateways until the patched version is deployed.
- Run analysis workloads under low-privilege service accounts to limit the blast radius of code execution.
# Upgrade uproot to a patched release
pip install --upgrade 'uproot>=5'
# Verify the installed version and commit
python -c "import uproot; print(uproot.__version__)"
# Optional: run analysis inside an isolated container
docker run --rm --network=none -v "$PWD":/data python:3.12 \
bash -c "pip install --upgrade uproot && python /data/analyze.py"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

