vLLM auto_map Dynamic Module RCE
vLLM can be tricked into running attacker-supplied Python code the moment it loads a model, before any API request arrives. This detection watches for the tell-tale two-step: the server reads a suspicious cached module file, then something spawns a shell or downloads/runs a binary in the same session shortly after.
How the attack works
An attacker publishes or modifies a Hugging Face model repo so its auto_map configuration points to a custom Python class. When vLLM initializes that model, it resolves auto_map entries through Transformers' dynamic-module loader without checking the trust_remote_code setting, so the attacker's code gets imported and run with the server's own privileges. Transformers first writes this code into a local cache directory under transformers_modules/<repo>/ and imports it. The rule watches for that cache file being read by the model server process (or its parent process in the same session), followed within a short window by that same session launching a shell, an inline interpreter one-liner, a network egress tool, or a binary from a temp directory. That follow-on process is the attacker's actual payload — reverse shell, downloader, credential theft, etc.
Netzilo detection
Netzilo reports this behaviour when it is observed.
- Signature ID
- 7b3d1c9e-4a52-4f18-9c60-2d8ea1f47b53
- Severity
- High
Why it matters
An attacker who controls or poisons a model repository can get arbitrary code execution on the machine hosting the vLLM server, before any inference request is even served, potentially leading to full host compromise, data theft, or lateral movement.
What you can do
- →Only load models from repositories you trust, and review auto_map / custom module code before deployment.
- →Run vLLM and other model servers with trust_remote_code disabled unless a specific model requires it, and audit any model that does require it.
- →Run model-serving processes with least privilege and in isolated environments (containers, restricted users, no outbound network by default) so a compromised loader can't easily spawn shells or reach the network.
- →Monitor for shell, interpreter, or temp-directory binary execution occurring shortly after a model load, especially from processes that also read files under ~/.cache/huggingface/modules/transformers_modules/.
Known benign look-alikes
- Models that legitimately require trust_remote_code (many community architectures) do read transformers_modules/*.py. The rule only reports when the same session also spawns a shell, inline interpreter, egress tool, or a binary from a temp directory within 10 minutes - but a legitimate remote-code model whose init path shells out (e.g. a custom tokenizer wrapper calling `sh -c`) will match.
- torch cpp_extension / custom CUDA kernel JIT builds spawn ninja, nvcc, cmake and compiler drivers. These are excluded by command-token filter, but a wrapper shell script that invokes the toolchain can still match.
- vLLM engine-core and multiprocessing workers spawn `python -c` (spawn_main, resource_tracker, forkserver). These specific invocations are excluded explicitly.
- Multi-node Ray/vLLM deployments that launch workers over `ssh` from the same process that loaded the model.
- CI pipelines that deliberately evaluate remote-code model repositories and run shell health checks or artifact uploads in the same initialisation window.