NeMo .nemo archive - torch.load(weights_only=False) RCE on Model.restore_from()
Bug
nemo-toolkit==2.5.0 (latest PyPI wheel as of 2026-05-12) loads .nemo archive weights via Python's standard deserializer with weights_only=False. Any attacker who hands a crafted .nemo file to Model.restore_from(path) (the canonical public API for loading NeMo models) achieves arbitrary code execution at load time, before any model instantiation.
Files
malicious.nemo - 10,240-byte malicious archive
build_poc.py - builds the malicious archive
trigger.py - calls SaveRestoreConnector._load_state_dict_from_disk directly
restore_from_trigger.py - calls Model.restore_from() (the documented public API)
repro.sh - one-command reproducer
Reproduce
Expected: /tmp/NEMO_AUDIT.txt is created with the line EXPLOIT CONFIRMED: PWNED by nemo .nemo load via torch.load(weights_only=False). repro.sh exits 0 on success.
Affected version
nemo-toolkit==2.5.0 (latest PyPI release as of 2026-05-12).
Distinguisher: the main branch already fixed this at commit 59854cbc9 (post-v2.5.0rc0 tag) by switching to weights_only=True. The released PyPI wheel is unfixed. Verify via:
1git show v2.5.0rc0:nemo/core/connectors/save_restore_connector.py | grep weights_only
2# weights_only=False
Affected file in NeMo source
nemo/core/connectors/save_restore_connector.py:756-758 in the shipped wheel:
1def _load_state_dict_from_disk(model_weights, map_location=None):
2 return torch.load(model_weights, map_location='cpu', weights_only=False)
Reach (call chain): Model.restore_from(...) → SaveRestoreConnector.load_config_and_state_dict() → _load_state_dict_from_disk() → sink. Also SaveRestoreConnector.extract_state_dict_from() → sink. Both are documented public APIs in the NeMo user guide.
Severity
CVSS 3.1 8.8 HIGH (AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H). User must call the load API on attacker-supplied bytes (UI:R), which is the documented intended workflow for sharing NeMo models. ML-multiplier eligible: NeMo models ARE the artifact, and restore_from is the canonical entry point.
Reporter
Tony Davis (lendtrain on huntr) - 2026-05-12.