# Diffusers has a `trust_remote_code` bypass via `custom_pipeline` and local custom components

Diffusers' trust_remote_code gate lived in download(), so custom_pipeline cross-repo and local-snapshot paths loaded and executed attacker Python despite trust_remote_code=False.

- Payout: Research
- Severity: high
- Program: Diffusers
- Found by: Vancir
- Disclosed: 2026-05-07
- CVE: CVE-2026-44513
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-98h9-4798-4q5v
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-98h9-4798-4q5v
- Tags: area:ai domain:ai domain:oss impact:rce kind:research platform:ghsa sev:high tech:python technique:source-review vuln:rce

**Target:** DiffusionPipeline.from_pretrained dynamic module loader (pipeline.py / custom component .py files)
**Root cause:** The trust_remote_code check was implemented inside DiffusionPipeline.download() instead of at the dynamic-module load site (get_cached_module_file), so any path that skipped or short-circuited download() bypassed the gate.
**Steps:**
1. Variant 1: call `DiffusionPipeline.from_pretrained('repoA', custom_pipeline='attacker/repoB', trust_remote_code=False)`; gate checks repoA's file list, repoB's `pipeline.py` is loaded and executed.
2. Variant 2: call `DiffusionPipeline.from_pretrained('/local/snapshot', custom_pipeline='attacker/repoB', trust_remote_code=False)`; local-path branch never calls download(), so repoB code executes.
3. Variant 3: call `DiffusionPipeline.from_pretrained('/local/snapshot', trust_remote_code=False)` where snapshot's `model_index.json` references custom component files like `unet/my_unet_model.py`; local path skips download() and component code executes.
4. Observe arbitrary Python execution on the victim host despite trust_remote_code=False.
**How found:** Reporter noticed the trust_remote_code gate was placed in download() rather than at the actual dynamic-module load chokepoint, then enumerated code paths (cross-repo custom_pipeline, local snapshot, local custom components) that reach the loader without passing through download().
**Exploitation:** Attacker publishes a Hub repo containing a malicious pipeline.py or custom component .py, then lures a victim into passing it as custom_pipeline (or into loading a local snapshot referencing it); the dynamic module loader imports and runs the file, giving silent RCE on the victim's machine.
**Insight:** When a security gate is enforced in a wrapper function rather than at the sink, enumerate every caller that reaches the sink by another route — here local-path branches and cross-repo references both skip the wrapper; the correct fix is at get_cached_module_file, the single load chokepoint.

