# ExecuTorch `.pte` — default Minimal verification bypass PoC model files Malicious ExecuTorch (`.pte`) model files that cause an out-of-bounds read and a controllable adjacent-heap information disclosure when loaded via the default C++ path (`Module::load` / `executor_runner` / `Program::load(loader)`), which uses `Verification::Minimal`. Tested on pytorch/executorch HEAD `ab45eb6` (`runtime/executor/program.cpp`). | File | Result | Sink | |---|---|---| | `et_oob_read.pte` | out-of-bounds READ during load (CWE-125) | `Program::load`, `program.cpp:251` | | `et_leak.pte` | controllable adjacent-heap info disclosure (CWE-200) | `get_method_name`, `program.cpp:366` | | `et_valid.pte` | loads cleanly (negative control) | — | ## Root cause The default load mode is `Verification::Minimal`, in which `VerifyProgramBuffer` is not called — only a root-offset bounds check runs. All subsequent FlatBuffers vtable/vector/string offsets from the `.pte` are dereferenced unvalidated: - `constant_segment->offsets()` (`program.cpp:251`) → OOB read during `Program::load`. - `get_method_name()` returns `name->c_str()` (`program.cpp:366`), an unvalidated FlatBuffers string offset; `c_str()` ignores the length prefix and reads to a NUL, so an attacker-chosen offset leaks arbitrary-location/length adjacent process memory through a public, loggable API. ## Reproduce Official tool `executor_runner` built with AddressSanitizer (uses `Module::load` = `Verification::Minimal` by default): ``` ./executor_runner --model_path et_oob_read.pte # heap-buffer-overflow READ at program.cpp:251 ./executor_runner --model_path et_valid.pte # loads cleanly ``` `leak_demo.py` shows attacker control over the disclosed memory location for `et_leak.pte`. Verifier-bypass proof: the same files loaded with `Verification::InternalConsistency` are cleanly rejected ("Verification failed", InvalidProgram, no crash) — the verifier would have caught them; the default Minimal path skips it. ## Suggested fix Make `InternalConsistency` the default for untrusted input, or bounds-check the string/vector offsets in Minimal mode, or document Minimal as trusted-input-only and have `Module`/`executor_runner` validate. Crash/leak-only proof of concept.