trust_remote_code and the ML Orchestration CVE Class
A second family of ML supply-chain CVEs has nothing to do with weights and everything to do with the glue: trust_remote_code and orchestration servers.
The deserialization CVE class gets most of the attention because “loading a model runs code” is a memorable headline. We cover that half in unsafe model deserialization and the pickle CVEs. But a second family of ML supply-chain CVEs has nothing to do with model weights and everything to do with the glue between them: the orchestration libraries that load custom model code, evaluate expressions, and render prompt templates. These are CWE-94 (code injection) and CWE-1336 (template injection) flaws, and they are arguably more dangerous in production because they execute on attacker-influenced input at runtime, not just on a one-time model load.
transformers and trust_remote_code
Hugging Face transformers supports models whose architecture is defined by Python files shipped in the model repository. Loading such a model with trust_remote_code=True imports and runs that code in your process. The flag exists because some legitimate architectures need it, and the documentation is explicit that you should only enable it for repositories you trust and ideally pin to a specific revision.
In practice the flag is copied from tutorials and left on. The moment it is set against a repository you do not control, “download this model” becomes “execute this repository’s code.” There is frequently no separate CVE for this — it is documented intended behavior — which is exactly why it is dangerous as a tracking problem: a defender scanning a CVE feed will not see “you enabled trust_remote_code on an untrusted repo,” yet it is functionally equivalent to the deserialization RCEs that do get CVEs. Treat it as a standing exposure to audit in your own code, not something the feed will surface for you.
langchain and the expression/eval surface
Where there is a CVE, the langchain ecosystem is the canonical case study. CVE-2023-29374 covered code execution in LLMMathChain: the chain took LLM output and evaluated it as a Python expression, so prompt-influenced text reached an eval-like sink. CVE-2024-21513 covered code execution in langchain-experimental through a similar path. These are CWE-94: untrusted text — and LLM output driven by user input is untrusted text — flowing into a code-generation or evaluation primitive.
The structural lesson generalizes past langchain. Any orchestration component that (a) takes model output and (b) feeds it to eval, exec, a math parser, a code interpreter tool, or a shell, is one prompt-injection away from RCE. The CVE history of these libraries is not a story about one buggy function; it is a series of independent rediscoveries that “LLM output is an untrusted input channel” applied to whatever sink was nearest.
Template injection: the quieter variant
Prompt templates are rendered by template engines. If user-controlled data is interpolated into a template that is itself rendered — rather than passed as a bound variable — you have CWE-1336 server-side template injection, and depending on the engine that ranges from data disclosure to code execution. This appears in ML stacks wherever prompt construction concatenates user input into a Jinja-style template instead of parameterizing it. It rarely produces a dramatic ML CVE, which is precisely why it survives in codebases: it looks like string formatting, not a sink. LangChain has produced several confirmed instances; see LangChain security vulnerabilities.
Reading these CVEs correctly
For this class the triage question is different from deserialization. It is not “did I produce these bytes” but: does untrusted runtime input — user prompts, retrieved documents, tool output — reach a code, expression, or template sink? A langchain code-execution CVE is critical for an app that pipes user chat into an agent with a Python tool, and close to irrelevant for an app that uses the library only for static, server-authored chains with no eval-capable tools. Same CVE, opposite exposure, and the CVSS vector — typically scored for the worst case — will not distinguish them. Your data-flow does.
What actually mitigates it
- Default
trust_remote_codeto off and pin revisions. If a model genuinely requires it, vendor and review the model code, then load it pinned to a reviewed commit — never a moving branch. - Keep model output away from code sinks. Do not
evalLLM output. Replace math/code chains with sandboxed, allow-listed evaluators, or remove the capability if the use case does not need it. - Parameterize prompts; never render user input as a template. Pass user data as bound variables to a template that is authored entirely by you.
- Treat orchestration libraries as a tracked CVE surface in their own right. langchain, langchain-experimental, transformers, llama-index and similar move fast and have a recurring code-execution history. Pin versions, watch their advisories specifically, and re-evaluate exposure when your agent’s tool list changes — not only when a CVE drops.
The class has since produced entries in the serving layer itself. CVE-2026-22807 (CVSS 9.8) records vLLM loading Hugging Face auto_map dynamic modules during model resolution without gating on trust_remote_code at all, and CVE-2026-27893 (8.8) records two vLLM model implementation files that hardcoded trust_remote_code=True, bypassing the operator’s own setting. Both are catalogued alongside the rest of the runtime record in inference server CVEs. They are the strongest argument yet that this flag cannot be treated as a decision you make once: a dependency can make it for you.
Weight-loading CVEs and orchestration CVEs are two halves of the same supply chain. The first asks whether you trust the bytes; the second asks whether you trust the inputs flowing through the glue at runtime. A tracker that only watches the first half is reporting on half the attack surface. Our ML CVE database overview covers what the public trackers do and do not capture, and model file format security covers what the bytes half looks like format by format.
Sources
- transformers: trust_remote_code documentation and warning
- CVE-2023-29374: LangChain LLMMathChain code execution — NVD
- CVE-2024-21513: langchain-experimental code execution — NVD
- CWE-94: Improper Control of Generation of Code (Code Injection) — MITRE
- CWE-1336: Improper Neutralization of Special Elements Used in a Template Engine — MITRE
ML CVEs — in your inbox
CVEs in ML libraries, frameworks, and the AI/ML supply chain. Sent only when there is something worth sending.
No spam. Unsubscribe anytime.
Related
MLflow CVEs: Why 2.14.1 Still Fails Your Scanner
MLflow carries 80 published advisories and 17 with no patched version. Why scanning 2.14.1 returns unfixable findings, and which ones need real action.
PyTorch Security: Notable CVEs and Hardening the Loading Path
PyTorch's most consequential CVEs cluster on one thing: loading a model file that runs code. A walk through the verified entries and how to harden.
Unsafe Model Deserialization: The Pickle Problem Behind ML CVEs
Loading a model file can execute arbitrary code. The most repeated vulnerability class in the ML supply chain: the real CVEs, why they recur, and what fixes it.