Published
- 5 min read
By Allan D - Editor, AI Security Wire
FaceHugger: Diffusers TOCTOU Flaws Let Model Repos Execute Code
Every time a developer calls DiffusionPipeline.from_pretrained() to load a model from Hugging Face Hub, they are trusting that the artifacts they download are what they appear to be. For millions of downloads per month, that trust has been misplaced. Zafran Labs published research on July 27 disclosing three vulnerabilities in the Hugging Face Diffusers library that allow a crafted model repository to execute arbitrary code on any machine that loads it, regardless of whether trust_remote_code is set to False.
The Hacker News covered the disclosures today as they gained broader attention. The vulnerabilities have been collectively named FaceHugger. They were patched in Diffusers version 0.38.0, released in early May 2026 — but Diffusers sees approximately 200,000 installs per day, and patch adoption in ML environments tends to lag.
What FaceHugger Actually Does
The Diffusers library uses a parameter called trust_remote_code that is supposed to control whether custom Python code hosted inside a model repository is allowed to run during the loading process. Setting it to False (or simply omitting it, which is the default) should block unreviewed code from executing. This is the documented safeguard.
Zafran Labs researchers Gal Zaban and Ido Shani found that the safeguard does not hold. Their analysis identified a root cause that affects all three CVEs: the model download process makes two sequential, non-atomic HTTP requests, but the trust_remote_code check runs only against the first. Anything that causes the code seen during the check to differ from what actually loads is an exploitation path.
The three CVEs break down as follows:
CVE-2026-44827 (CVSS 8.8): A code injection vulnerability exploiting the custom_pipeline loading flow. An attacker crafts a repository containing a pipeline file named None.py. The naming convention bypasses the trust gate’s logic for how it resolves pipeline names, so the file loads and executes despite trust_remote_code=False.
CVE-2026-45804 (CVSS 7.5): A genuine race condition. Repository contents are modified between the hf_hub_download call (where the check runs) and the snapshot_download call (where the actual files are retrieved). Because these are two separate HTTP requests, the attacker controls what the second request returns without the security gate seeing it.
CVE-2026-44513 (CVSS 8.8): Another code injection via the custom_pipeline flow, using a different bypass path through how the library resolves the custom pipeline name into a file path and imports it, again without the trust check catching it.
The researchers summarize the core issue cleanly: “the trust check lives entirely in the first phase. Therefore, any method that makes the loader see custom code that the gate did not, allows bypassing the trust_remote_code mechanism.”
Why This Matters Beyond a Single Library
Diffusers is not a niche tool. It is the standard Python library for state-of-the-art diffusion models — Stable Diffusion, FLUX, Sora-derivative models, video generation pipelines. It is embedded in CI/CD systems, container images, production inference pipelines, and developer workstations. The package logged 8.1 million downloads in July 2026 alone.
The supply chain angle is what makes FaceHugger meaningful beyond a standard CVE disclosure. Hugging Face Hub has become the GitHub of AI model distribution: organisations load models from it the way they load packages from npm or PyPI. The same trust assumptions that created the npm supply chain attack surface are being replicated in the AI model space. A malicious model repository on Hub can reach any machine running a vulnerable version of Diffusers that loads it — including automated pipelines where no human reviews the load operation.
Zafran noted in their research that this connects to a broader pattern in AI security: artifacts pulled from AI repositories are frequently treated as passive data, when configuration files, loaders, and custom pipeline code can cross into executable code. The same researchers previously published work on DifyTap (a cross-tenant exfiltration vulnerability in Dify) and ChainLeak (a related supply chain issue), both of which have been reported on separately.
Patch and Workaround
Patch: Upgrade to Hugging Face Diffusers 0.38.0 or later. The fix addresses the non-atomic download problem and strengthens the trust_remote_code validation to run against the resolved, final code rather than the first response.
If immediate patching isn’t possible, the project maintainers recommend:
- Only call
from_pretrainedwith repository sources that have been fully audited and are trusted - Do not pass
custom_pipeline=pointing at a Hub repository different from the primarypretrained_model_name_or_pathwithout reading itspipeline.pyfirst - Before loading from a local snapshot, inspect the directory for unexpected
.pyfiles, particularly in component subdirectories (unet/,scheduler/,vae/) and the snapshot root
Any organisation running automated model loading pipelines from Hugging Face Hub should verify their Diffusers version. The 0.38.0 release was from early May, which means any deployment not actively maintained since then is still vulnerable. For environments pulling models from untrusted or public Hub repositories, the exposure is significant: a poisoned repository can silently achieve code execution on the host running the load.
The prior Hugging Face Transformers RCE via config injection (CVE-2026-4372, covered previously) showed that the model loading attack surface is real and actively researched. FaceHugger shows the pattern continues and extends into the Diffusers ecosystem.
References
Frequently Asked Questions
- What is trust_remote_code and why is bypassing it a big deal?
- trust_remote_code is a parameter in Hugging Face libraries that controls whether custom Python code hosted in a model repository is allowed to execute when loading a model. Setting it to False or omitting it is supposed to block unreviewed code from running. FaceHugger shows that this safeguard can be bypassed entirely, meaning a malicious model repository can execute code on a machine even when the developer explicitly opted out of custom code execution. That turns a routine model download into an initial access vector with no obvious warning to the user.
- How does the TOCTOU flaw work in Diffusers model loading?
- Diffusers downloads model files using two sequential, non-atomic HTTP requests rather than a single atomic operation. The trust_remote_code security check runs only against the first request. If an attacker can modify repository contents between the first and second request (CVE-2026-45804, the race condition variant), or can structure repository contents so that the code seen during the check differs from what actually executes (CVE-2026-44827 and CVE-2026-44513), the safeguard does not catch the malicious payload. The model loads, the code runs, and the developer has no indication anything unusual occurred.
- Are there workarounds if upgrading to Diffusers 0.38.0 isn't immediately possible?
- Yes. Hugging Face and Zafran recommend only calling from_pretrained with pretrained_model_name_or_path and custom_pipeline arguments that point to fully trusted, audited sources. Avoid passing custom_pipeline pointing to a different Hub repository than the primary model before reading its pipeline.py. If loading from a local snapshot, inspect the snapshot directory for unexpected .py files, particularly in component subdirectories like unet/, scheduler/, and vae/, and at the snapshot root, before loading.