--- license: mit tags: - security - poc --- # 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 with `Exploit.__reduce__` calling `eval(...)`, strips `builtins` out of `.data/extern_modules`, then loads it through a `PackageImporter` locked down with `module_allowed=lambda m: False`. Prints whether `module_allowed` got 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 of `reproduce.py`, against the pre-built `.pt` file. ## Reproduce ```bash 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).