CVE-2026-45804
Diffusers: TOCTOU Trust Remote Code Bypass
Diffusers is the a library for pretrained diffusion models. Prior to 0.38.0, Diffusers' DiffusionPipeline.from_pretrained flow can bypass the trust_remote_code guard because download() validates model_index.json and custom pipeline code before later loading from a cached folder that can change, allowing a Hub repository with custom .py pipeline code to execute through the custom pipeline flow without passing custom_pipeline or trust_remote_code=True. This issue is fixed in version 0.38.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
7.5
Diffusers: TOCTOU Trust Remote Code Bypass
Diffusers is the a library for pretrained diffusion models. Prior to 0.38.0, Diffusers' DiffusionPipeline.from_pretrained flow can bypass the trust_remote_code guard because download() validates model_index.json and custom pipeline code before later loading from a cached folder that can change, allowing a Hub repository with custom .py pipeline code to execute through the custom pipeline flow without passing custom_pipeline or trust_remote_code=True. This issue is fixed in version 0.38.0.
- Record
CVE-2026-45804- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-367
- Updated
- 2026-11-02
EUVDEUVD-2026-44711
7.5
Diffusers is the a library for pretrained diffusion models. Prior to 0.38.0, Diffusers' DiffusionPipeline.from_pretrained flow can bypass the trust_remote_code guard because download() validates model_index.json and custom pipeline code before later loading from a cached folder that can change, allowing a Hub repository with custom .py pipeline code to execute through the custom pipeline flow without passing custom_pipeline or trust_remote_code=True. This issue is fixed in version 0.38.0.
- Record
EUVD-2026-44711- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-7wx4-6vff-v64p
7.5
Diffusers: TOCTOU Trust Remote Code Bypass
Background
This vulnerability is found in the diffusers package - the transformers-equivalent library for diffusion models.
It is found in the DiffusionPipeline.from_pretrained flow, which is used to load a pipeline from the HuggingFace Hub.
This function has a trust_remote_code guard: if the repository’s model_index.json references a custom pipeline class defined in a .py file in the repo, the load is blocked unless trust_remote_code=True is explicitly passed:
ValueError: The repository for attacker/repo contains custom code in pipeline.py
which must be executed to correctly load the model. You can inspect the repository
content at https://hf.co/attacker/repo/blob/main/pipeline.py.
Please pass the argument `trust_remote_code=True` to allow custom code to be run.
The vulnerability allows arbitrary code execution through the custom pipeline flow from a Hub repo, with no custom_pipeline or trust_remote_code kwargs passed. The from_pretrained call succeeds and returns a functional pipeline.
Naive Flow
DiffusionPipeline.from_pretrained begins by popping all relevant arguments from kwargs into local variables, then calls DiffusionPipeline.download() to fetch the repo files:
# pipeline_utils.py:853
cached_folder = cls.download(
pretrained_model_name_or_path,
...
custom_pipeline=custom_pipeline,
trust_remote_code=trust_remote_code,
...
)
Inside download(), model_index.json is fetched first as a standalone file via hf_hub_download:
# pipeline_utils.py:1636
config_file = hf_hub_download(
pretrained_model_name,
cls.config_name,
...
)
config_dict = cls._dict_from_json_file(config_file)
This config is used to detect custom pipeline code and enforce the trust check:
# pipeline_utils.py:1672
if custom_pipeline is None and isinstance(config_dict["_class_name"], (list, tuple)):
custom_pipeline = config_dict["_class_name"][0]
load_pipe_from_hub = custom_pipeline is not None and f"{custom_pipeline}.py" in filenames
if load_pipe_from_hub and not trust_remote_code:
raise ValueError(...)
After the check passes, snapshot_download then fetches all files and saves them to disk:
# pipeline_utils.py:1778
cached_folder = snapshot_download(
pretrained_model_name,
...
revision=revision,
allow_patterns=allow_patterns,
...
)
Back in from_pretrained, the config is read a second time from the downloaded snapshot, and_resolve_custom_pipeline_and_cls reads the config to re-check if custom code needs to be loaded:
# pipeline_loading_utils.py:974
def _resolve_custom_pipeline_and_cls(folder, config, custom_pipeline):
custom_class_name = None
if os.path.isfile(os.path.join(folder, f"{custom_pipeline}.py")):
custom_pipeline = os.path.join(folder, f"{custom_pipeline}.py")
elif isinstance(config["_class_name"], (list, tuple)) and os.path.isfile(
os.path.join(folder, f"{config['_class_name'][0]}.py")
):
custom_pipeline = os.path.join(folder, f"{config['_class_name'][0]}.py")
custom_class_name = config["_class_name"][1]
return custom_pipeline, custom_class_name
If the config points to a .py file, it is imported.
The Vulnerability
hf_hub_download and snapshot_download are two independent HTTP calls to the Hub, both resolving the repository’s default branch (if revision=None) to its current HEAD at call time. There is no atomicity guarantee between them - if the repository is updated between the two calls, they will resolve to different commits and download different content, with no warning displayed to the user.
The trust check in download() operates on the content fetched by hf_hub_download (commit A). The snapshot_download call that immediately follows can silently fetch a newer commit (commit B). The config in the newer commit will be the one parsed by…
- Record
GHSA-7wx4-6vff-v64p- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-367
- Updated
- 2026-11-02
NVD
7.5
Diffusers is the a library for pretrained diffusion models. Prior to 0.38.0, Diffusers' DiffusionPipeline.from_pretrained flow can bypass the trust_remote_code guard because download() validates model_index.json and custom pipeline code before later loading from a cached folder that can change, allowing a Hub repository with custom .py pipeline code to execute through the custom pipeline flow without passing custom_pipeline or trust_remote_code=True. This issue is fixed in version 0.38.0.
- Record
CVE-2026-45804- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-367
- Updated
- 2026-11-02
OSV
7.5
Diffusers: TOCTOU Trust Remote Code Bypass
Diffusers is the a library for pretrained diffusion models. Prior to 0.38.0, Diffusers' DiffusionPipeline.from_pretrained flow can bypass the trust_remote_code guard because download() validates model_index.json and custom pipeline code before later loading from a cached folder that can change, allowing a Hub repository with custom .py pipeline code to execute through the custom pipeline flow without passing custom_pipeline or trust_remote_code=True. This issue is fixed in version 0.38.0.
- Record
CVE-2026-45804- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-367
- Updated
- 2026-11-02
OSVGHSA-7wx4-6vff-v64p
7.5
Diffusers: TOCTOU Trust Remote Code Bypass
Background
This vulnerability is found in the diffusers package - the transformers-equivalent library for diffusion models.
It is found in the DiffusionPipeline.from_pretrained flow, which is used to load a pipeline from the HuggingFace Hub.
This function has a trust_remote_code guard: if the repository’s model_index.json references a custom pipeline class defined in a .py file in the repo, the load is blocked unless trust_remote_code=True is explicitly passed:
ValueError: The repository for attacker/repo contains custom code in pipeline.py
which must be executed to correctly load the model. You can inspect the repository
content at https://hf.co/attacker/repo/blob/main/pipeline.py.
Please pass the argument `trust_remote_code=True` to allow custom code to be run.
The vulnerability allows arbitrary code execution through the custom pipeline flow from a Hub repo, with no custom_pipeline or trust_remote_code kwargs passed. The from_pretrained call succeeds and returns a functional pipeline.
Naive Flow
DiffusionPipeline.from_pretrained begins by popping all relevant arguments from kwargs into local variables, then calls DiffusionPipeline.download() to fetch the repo files:
# pipeline_utils.py:853
cached_folder = cls.download(
pretrained_model_name_or_path,
...
custom_pipeline=custom_pipeline,
trust_remote_code=trust_remote_code,
...
)
Inside download(), model_index.json is fetched first as a standalone file via hf_hub_download:
# pipeline_utils.py:1636
config_file = hf_hub_download(
pretrained_model_name,
cls.config_name,
...
)
config_dict = cls._dict_from_json_file(config_file)
This config is used to detect custom pipeline code and enforce the trust check:
# pipeline_utils.py:1672
if custom_pipeline is None and isinstance(config_dict["_class_name"], (list, tuple)):
custom_pipeline = config_dict["_class_name"][0]
load_pipe_from_hub = custom_pipeline is not None and f"{custom_pipeline}.py" in filenames
if load_pipe_from_hub and not trust_remote_code:
raise ValueError(...)
After the check passes, snapshot_download then fetches all files and saves them to disk:
# pipeline_utils.py:1778
cached_folder = snapshot_download(
pretrained_model_name,
...
revision=revision,
allow_patterns=allow_patterns,
...
)
Back in from_pretrained, the config is read a second time from the downloaded snapshot, and_resolve_custom_pipeline_and_cls reads the config to re-check if custom code needs to be loaded:
# pipeline_loading_utils.py:974
def _resolve_custom_pipeline_and_cls(folder, config, custom_pipeline):
custom_class_name = None
if os.path.isfile(os.path.join(folder, f"{custom_pipeline}.py")):
custom_pipeline = os.path.join(folder, f"{custom_pipeline}.py")
elif isinstance(config["_class_name"], (list, tuple)) and os.path.isfile(
os.path.join(folder, f"{config['_class_name'][0]}.py")
):
custom_pipeline = os.path.join(folder, f"{config['_class_name'][0]}.py")
custom_class_name = config["_class_name"][1]
return custom_pipeline, custom_class_name
If the config points to a .py file, it is imported.
The Vulnerability
hf_hub_download and snapshot_download are two independent HTTP calls to the Hub, both resolving the repository’s default branch (if revision=None) to its current HEAD at call time. There is no atomicity guarantee between them - if the repository is updated between the two calls, they will resolve to different commits and download different content, with no warning displayed to the user.
The trust check in download() operates on the content fetched by hf_hub_download (commit A). The snapshot_download call that immediately follows can silently fetch a newer commit (commit B). The config in the newer commit will be the one parsed by…
- Record
GHSA-7wx4-6vff-v64p- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-367
- Updated
- 2026-11-02
OSVPYSEC-2026-2446
7.5
Diffusers: TOCTOU Trust Remote Code Bypass
Background
This vulnerability is found in the diffusers package - the transformers-equivalent library for diffusion models.
It is found in the DiffusionPipeline.from_pretrained flow, which is used to load a pipeline from the HuggingFace Hub.
This function has a trust_remote_code guard: if the repository’s model_index.json references a custom pipeline class defined in a .py file in the repo, the load is blocked unless trust_remote_code=True is explicitly passed:
ValueError: The repository for attacker/repo contains custom code in pipeline.py
which must be executed to correctly load the model. You can inspect the repository
content at https://hf.co/attacker/repo/blob/main/pipeline.py.
Please pass the argument `trust_remote_code=True` to allow custom code to be run.
The vulnerability allows arbitrary code execution through the custom pipeline flow from a Hub repo, with no custom_pipeline or trust_remote_code kwargs passed. The from_pretrained call succeeds and returns a functional pipeline.
Naive Flow
DiffusionPipeline.from_pretrained begins by popping all relevant arguments from kwargs into local variables, then calls DiffusionPipeline.download() to fetch the repo files:
# pipeline_utils.py:853
cached_folder = cls.download(
pretrained_model_name_or_path,
...
custom_pipeline=custom_pipeline,
trust_remote_code=trust_remote_code,
...
)
Inside download(), model_index.json is fetched first as a standalone file via hf_hub_download:
# pipeline_utils.py:1636
config_file = hf_hub_download(
pretrained_model_name,
cls.config_name,
...
)
config_dict = cls._dict_from_json_file(config_file)
This config is used to detect custom pipeline code and enforce the trust check:
# pipeline_utils.py:1672
if custom_pipeline is None and isinstance(config_dict["_class_name"], (list, tuple)):
custom_pipeline = config_dict["_class_name"][0]
load_pipe_from_hub = custom_pipeline is not None and f"{custom_pipeline}.py" in filenames
if load_pipe_from_hub and not trust_remote_code:
raise ValueError(...)
After the check passes, snapshot_download then fetches all files and saves them to disk:
# pipeline_utils.py:1778
cached_folder = snapshot_download(
pretrained_model_name,
...
revision=revision,
allow_patterns=allow_patterns,
...
)
Back in from_pretrained, the config is read a second time from the downloaded snapshot, and_resolve_custom_pipeline_and_cls reads the config to re-check if custom code needs to be loaded:
# pipeline_loading_utils.py:974
def _resolve_custom_pipeline_and_cls(folder, config, custom_pipeline):
custom_class_name = None
if os.path.isfile(os.path.join(folder, f"{custom_pipeline}.py")):
custom_pipeline = os.path.join(folder, f"{custom_pipeline}.py")
elif isinstance(config["_class_name"], (list, tuple)) and os.path.isfile(
os.path.join(folder, f"{config['_class_name'][0]}.py")
):
custom_pipeline = os.path.join(folder, f"{config['_class_name'][0]}.py")
custom_class_name = config["_class_name"][1]
return custom_pipeline, custom_class_name
If the config points to a .py file, it is imported.
The Vulnerability
hf_hub_download and snapshot_download are two independent HTTP calls to the Hub, both resolving the repository’s default branch (if revision=None) to its current HEAD at call time. There is no atomicity guarantee between them - if the repository is updated between the two calls, they will resolve to different commits and download different content, with no warning displayed to the user.
The trust check in download() operates on the content fetched by hf_hub_download (commit A). The snapshot_download call that immediately follows can silently fetch a newer commit (commit B). The config in the newer commit will be the one parsed by…
- Record
PYSEC-2026-2446- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
diffusersPyPI |
before 0.38.0 | 0.38.0 |
diffusersPyPI |
before 0.38.0, plus listed versions 0.0.10.0.20.0.30.0.40.1.0 Show 45 moreShow less0.1.10.1.20.1.30.10.00.10.10.10.20.11.00.11.10.12.00.12.10.13.00.13.10.14.00.15.00.15.10.16.00.16.10.17.00.17.10.18.00.18.10.18.20.19.00.19.10.19.20.19.30.2.00.2.10.2.20.2.30.2.40.20.00.20.10.20.20.21.00.21.10.21.20.21.30.21.40.22.00.22.10.22.20.22.30.23.00.23.1 |
0.38.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-45804 is a high vulnerability (CVSS 7.5) in Huggingface Diffusers, published May 20, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.37%, the 31st percentile. Fixed in diffusers 0.38.0.
References
github.com/huggingface/diffusers/security/advisories/GHSA-7wx4-6vff-v64p
github.com/huggingface/diffusers/issues/13446
github.com/huggingface/diffusers/pull/13448
github.com/huggingface/diffusers/commit/a37f6f8394ac2a7ee8360c3abea811efe54512b1
github.com/huggingface/diffusers/releases/tag/v0.38.0
nvd.nist.gov/vuln/detail/CVE-2026-45804
Left out here: 46 versions and the rest of 3 source descriptions. The JSON record has them.