Remote artifact loaded with trust_remote_code=True

ID

trust-remote-code

Severity

critical

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

OWASP LLM

LLM03:2025 — Supply Chain

OWASP ASI

ASI05:2026 (secondary)

Family

LLM03 — Supply Chain

Red-team vectors

Sandbox Escape / RCE

Tags

ai_security

Description

Hugging Face loaders (from_pretrained(…​), load_dataset(…​), pipeline(…​), SentenceTransformer(…​) across the transformers, datasets, sentence-transformers and diffusers libraries) accept trust_remote_code=True, which downloads and executes the hub repository’s custom Python code at load time. This is the canonical remote-code-execution vector via model/dataset repositories: an attacker who compromises (or typosquats) the repo injects code that runs with the privileges of the loading context — CI/CD, a training job, or production inference — with no further exploitation required.

The AST path reads the trust_remote_code keyword off the call signature (argument order and multi-line calls are handled); trust_remote_code=False or an absent flag produces no finding. Jupyter notebooks are covered by a line-level floor.

Examples

from transformers import AutoModel
model = AutoModel.from_pretrained('user/model', trust_remote_code=True)   (1)
ds = load_dataset('user/dataset', trust_remote_code=True)                 (1)
st = SentenceTransformer('user/embedder', trust_remote_code=True)         (1)
1 The remote repo’s custom code executes on load — flagged critical.

AutoModel.from_pretrained('bert-base-uncased') (no flag) produces no finding.

Mitigation / Fix

  • Remove trust_remote_code=True — the built-in classes cover standard architectures.

  • If remote code is unavoidable, pin the artifact to an immutable revision=<commit hash> and review the repository’s custom code before loading.

  • Restrict artifact sources to an allowlist of trusted organizations.