# Huntr Submission Draft: TensorRT Polygraphy Serialized Plugin ACE ## Recommended Category Model File Vulnerability - Arbitrary Code Execution at model load/inspection time. Frame this as TensorRT `.engine` load-time ACE through a common model inspection tool. Do not frame it as a generic TensorRT library misuse or as a low-value scanner coverage gap. ## Title Polygraphy auto-enables trusted TensorRT plan host code, executing serialized plugin constructors from a `.engine` file during inspection ## Target TensorRT serialized engine (`.engine`, `.trt`, `.mytrtfile`) - NVIDIA ## Severity Critical ## Public PoC Model Repository https://huggingface.co/noshkas/tensorrt-polygraphy-serialized-plugin-ace-poc ## Summary Polygraphy's TensorRT engine loader enables `runtime.engine_host_code_allowed = True` before deserializing arbitrary engine bytes. TensorRT version-compatible plans can serialize plugin shared libraries into the engine file. A crafted `.engine` file can therefore carry a native shared object whose constructor executes during a normal model inspection command: ```bash cd "$RUN_DIR" polygraphy inspect model model.engine ``` In the PoC, the embedded native constructor writes a harmless marker file when `TRT_PLUGIN_MARKER` is set. The original plugin `.so` was removed from disk before inspection, and the isolated directory contained only `model.engine`, proving the code was loaded from the engine file. Polygraphy still fails to deserialize the intentionally incomplete plugin after the constructor runs, so the user sees a failed inspection even though host code already executed. This is specifically the Polygraphy auto-trust path during inspection. The victim does not explicitly call `IRuntime::setEngineHostCodeAllowed()` or provide a separate plugin library path. ## Impact An attacker can publish a malicious TensorRT engine that embeds native host code. A researcher, CI job, model registry, or security gate that uses Polygraphy to inspect community TensorRT engines can execute attacker-controlled native code simply by inspecting the model file. Organizations using model inspection as a safety gate before loading community engines could pass a malicious file into Polygraphy and execute attacker-controlled code before any inspection result is returned. ## Affected Versions Tested - Polygraphy: `0.49.26` - TensorRT Python package: `tensorrt-cu12==10.16.1.11` - TensorRT lean runtime package: `tensorrt-lean-cu12==10.16.1.11` - OS: Ubuntu 24.04 - GPU: NVIDIA GeForce RTX 5090 - Driver: 570.195.03 - Python: 3.12.3 ## Root Cause Polygraphy reads the engine file bytes and then sets the TensorRT runtime trust flag before deserialization: ```python runtime.engine_host_code_allowed = True ``` TensorRT documents `engine_host_code_allowed` as the flag required for trusted plans that may contain host code. TensorRT also documents `IBuilderConfig::setPluginsToSerialize` / `plugins_to_serialize`, which serializes plugin shared libraries into version-compatible engines. When such an engine is loaded with host code allowed, the serialized shared library is loaded and its constructor runs. Polygraphy's default inspection workflow therefore turns a model file inspection into a host-code execution sink. ## Reproduction Steps Use an isolated CUDA/TensorRT host. ```bash cd "$RUN_DIR" python3 -m venv .venv . .venv/bin/activate python -m pip install --upgrade pip wheel setuptools python -m pip install polygraphy==0.49.26 tensorrt-cu12==10.16.1.11 tensorrt-lean-cu12==10.16.1.11 ``` Download the PoC model file from the public Hugging Face repository, then run: ```bash cd "$RUN_DIR" export LD_LIBRARY_PATH="$RUN_DIR/.venv/lib/python3.12/site-packages/tensorrt_lean_libs:${LD_LIBRARY_PATH:-}" export TRT_PLUGIN_MARKER="$RUN_DIR/marker.txt" rm -f "$TRT_PLUGIN_MARKER" polygraphy inspect model "$RUN_DIR/model.engine" cat "$TRT_PLUGIN_MARKER" ``` Expected marker output: ```text marker_constructor pid= time= ``` Expected Polygraphy output also includes a deserialization failure: ```text SymbolAddress for getCreators could not be loaded Could not deserialize engine. See log for details. ``` The marker is written before that failure. ## Reproduction From Generator Script The included `trt_serialized_plugin_marker_probe.py` generates the engine and runs negative controls: ```bash cd "$RUN_DIR" python trt_serialized_plugin_marker_probe.py --out results/trt_serialized_plugin_marker_probe.json ``` The script: 1. Builds a harmless native shared library with a constructor gated by `TRT_PLUGIN_MARKER`. 2. Builds a version-compatible TensorRT engine with `config.plugins_to_serialize = ["libmarker_payload.so"]`. 3. Removes the original `.so` before loading. 4. Confirms `runtime.engine_host_code_allowed = False` does not execute the marker. 5. Confirms `runtime.engine_host_code_allowed = True` executes the marker. 6. Confirms `polygraphy inspect model model.engine` executes the marker. ## Evidence PoC engine: ```text SHA256: 777cdecefc51699d43862522dd7ea92ec377f2dd9b25d40aa00b72edd74ad758 Size: 111219596 bytes ``` Primary result: ```json { "deserialize_false": { "allow_host_code": false, "marker_changed": false, "ok": false }, "deserialize_true": { "allow_host_code": true, "marker_changed": true, "ok": false }, "polygraphy_inspect": { "returncode": 1, "marker_changed": true } } ``` Isolated proof: ```text marker_constructor pid=1209 time=1778689895 ``` Default command proof, without `--model-type=engine`: ```text marker_constructor pid=1356 time=1778690022 ``` Negative control: A version-compatible engine without a serialized plugin inspected successfully and did not create a marker. ## Distinction From Nearby Pending Reports Huntr's public TensorRT listings show pending report titles involving `IRuntime::loadRuntime()` and `setEngineHostCodeAllowed()`. The body/details are not public, so I cannot verify whether they cover this exact path. This report is distinct because the trigger is Polygraphy's normal model-inspection command. The user does not explicitly opt into trusted host code. Polygraphy automatically sets the TensorRT trust flag and deserializes the model file, allowing a serialized plugin constructor embedded in the `.engine` to execute during inspection. ## Official References - Huntr Participation Guidelines: https://huntr.com/guidelines - TensorRT `IBuilderConfig::setPluginsToSerialize`: https://docs.nvidia.com/deeplearning/tensorrt/latest/_static/c-api/classnvinfer1_1_1_i_builder_config.html - TensorRT Plugin API serialized plugin library loading: https://docs.nvidia.com/deeplearning/tensorrt/latest/inference-library/plugins-api-migration.html - TensorRT version-compatible plans and `engine_host_code_allowed`: https://docs.nvidia.com/deeplearning/tensorrt/10.13.3/inference-library/advanced.html - Polygraphy loader source: https://docs.nvidia.com/deeplearning/tensorrt/latest/_static/polygraphy/_modules/polygraphy/backend/trt/loader.html ## Suggested Remediation Polygraphy should not silently enable `engine_host_code_allowed` for untrusted engine files. Require an explicit command-line opt-in such as `--allow-engine-host-code`, display a strong warning, and default to rejecting TensorRT plans that require host code during inspection. For safer inspection workflows, parse metadata without deserializing host-code-carrying plans where possible, or run deserialization in a sandboxed worker with no filesystem/network access.