torch.package module_allowed security callback bypass -> RCE
PoC for a huntr Model File Vulnerability (MFV) report against the PyTorch Package (.pt)
format (torch.package). This is a separate, distinct root cause from the earlier
torch-package-interned-module-rce-poc submission (interned-module exec()).
The bug
PackageImporter.__init__ calls module_allowed(extern_module) for every name in
self.extern_modules (read from .data/extern_modules in the archive), and raises if
it returns False. This is the only documented trust-boundary parameter the API
offers -- the docstring says it exists so callers can "ensure packages loaded do not
depend on modules that the server does not support."
Separately, _load_module()'s fallback path -- reached whenever the module tree lookup
misses -- checks a hardcoded IMPLICIT_IMPORT_ALLOWLIST (numpy, numpy.core,
numpy.core._multiarray_umath, builtins) and, if the name is on it, does
importlib.import_module(name) immediately. It never calls module_allowed.
If an attacker crafts a .pt archive where .data/extern_modules simply doesn't
mention builtins (trivial -- just don't write that line, no need to go through the
real PackageExporter API at all for the final artifact), module_allowed('builtins')
is never invoked. find_class('builtins', 'eval') still resolves successfully through
the IMPLICIT_IMPORT_ALLOWLIST fallback. A developer who follows the docs and passes
module_allowed=lambda m: False to lock everything down is still fully exploitable.
Files
reproduce.py-- full repro: builds a package withExploit.__reduce__callingeval(...), stripsbuiltinsout of.data/extern_modules, then loads it through aPackageImporterlocked down withmodule_allowed=lambda m: False. Prints whethermodule_allowedgot called (it doesn't) and creates/tmp/torch_package_builtins_bypass_pwned.build_payload.py/malicious_builtins_stripped.pt-- the payload build script and a pre-built copy of the malicious archive.trigger_stripped.py-- just the load-and-verify half ofreproduce.py, against the pre-built.ptfile.
Reproduce
pip install torch
python3 reproduce.py
ls -la /tmp/torch_package_builtins_bypass_pwned # created despite module_allowed=False
Full report: huntr.com MFV submission (PyTorch Package format).