CVE-2026-44827: Diffusers Diffusers Has A `trust_remote_code` Bypass Vulnerability
HIGHCVE-2026-44827 is a HIGH (CVSS 8.8) diffusers has a `trust_remote_code` bypass vulnerability (CWE-94: Improper Control of Generation of Code ('Code Injection')) affecting Diffusers libraries in the PyPI ecosystem. The issue involves diffusers has a `trust_remote_code` bypass via `custom_pipeline` and local custom components. Remediation is available by upgrading affected packages to version 0.38.0.
CVE-2026-44827 at a Glance
Security Impact
CVSS: 8.8
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H).
How to Fix CVE-2026-44827
To remediate this vulnerability, upgrade all affected Diffusers dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
pip install diffusers>=0.38.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
pip show diffusers
How to Check if You Are Affected
To determine whether your Python environment is affected by CVE-2026-44827, inspect your installed packages using pip:
pip show diffusers
Analyze the terminal output to locate any version of Diffusers in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.38.0), your application is affected.
Note: The pip show diffusers command checks currently installed packages in your active Python environment.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-94: Improper Control of Generation of Code ('Code Injection'), where the product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment. In Diffusers, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-44827 Affected Diffusers Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
diffusers
|
PyPI |
< 0.38.0
|
0.38.0
|
References
Frequently Asked Questions
What is CVE-2026-44827?
Which Diffusers versions are affected?
What version fixes CVE-2026-44827?
Is diffusers affected?
What is the CVSS score of CVE-2026-44827?
What CWE is associated with CVE-2026-44827?
How can I check PyPI dependencies for CVE-2026-44827?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-j7w6-vpvq-j3gm",
"modified" : "2026-06-05T17:53:00Z",
"published" : "2026-05-07T02:24:22Z",
"withdrawn" : "2026-05-07T05:25:32Z",
"aliases" : [ "CVE-2026-44827" ],
"summary" : "Diffusers has a `trust_remote_code` bypass via `custom_pipeline` and local custom components",
"details" : "## Background\n\nThis vulnerability is found in the `DiffusionPipeline.from_pretrained` flow, which is used to load a pipeline from the HuggingFace Hub.\n\nThis function accepts an optional `custom_pipeline` keyword argument: the name of a Python file in the repo that contains a custom class inheriting from `DiffusionPipeline`. An equivalent flow is triggered when the `_class_name` field in `model_index.json` (the repo config file) is set to a custom class.\n\nAny attempt to use a custom pipeline throws the following exception, requesting that `trust_remote_code` is also passed:\n\n```python\nDiffusionPipeline.from_pretrained(\n pretrained_model_name_or_path='ido-shani/custom-pipeline',\n custom_pipeline=\"custom\"\n)\n\nValueError: The repository for ido-shani/custom-pipeline contains custom code in\ncustom.py which must be executed to correctly load the model. You can inspect the\nrepository content at https://hf.co/ido-shani/custom-pipeline/blob/main/custom.py.\nPlease pass the argument `trust_remote_code=True` to allow custom code to be run.\n```\n\nThe vulnerability is a silent RCE - it allows arbitrary code to be loaded through the custom\\_pipeline flow from a Hub repo, with no `custom_pipeline` or `trust_remote_code` kwargs and nothing suspicious in the config. The `from_pretrained` call succeeds and returns a functional pipeline.\n\n## Naive Flow\n\nFirst, all relevant arguments are popped from kwargs and stored in local variables.\n\nGiven a `pretrained_model_name_or_path` that is a Hub repo ID, `DiffusionPipeline.download()` is called. This function serves two roles: it orchestrates downloading relevant model files, and it is the security gatekeeper for `trust_remote_code`. It is called even if the model is already cached; in that case it exits early. If the repo contains custom code, it checks whether `trust_remote_code` was passed and raises otherwise:\n\n```python\n# pipeline_utils.py:1645-1652\nload_pipe_from_hub = custom_pipeline is not None and f\"{custom_pipeline}.py\" in filenames\n\n...\n\nif load_pipe_from_hub and not trust_remote_code:\n raise ValueError(...)\n```\n\nIt then runs `_get_pipeline_class`, which returns the class object of the pipeline in order to inspect its `__init__` signature and determine which component files need to be downloaded. As part of building the `allow_patterns` list used to filter the snapshot download to necessary files only, the custom pipeline file is explicitly included if present:\n\n```python\n# pipeline_utils.py:1707\nallow_patterns += [f\"{custom_pipeline}.py\"] if f\"{custom_pipeline}.py\" in filenames else []\n```\n\nThe function then checks if all expected files are already present, and either exits early or triggers a snapshot download with those patterns.\n\nThe next step in `from_pretrained` is loading the pipeline class a second time, this time to actually instantiate it. Before calling `_get_pipeline_class` again, `_resolve_custom_pipeline_and_cls` is called to translate the `custom_pipeline` name into a local path, since the files have already been downloaded:\n\n```python\n# pipeline_loading_utils.py:965-974\ndef _resolve_custom_pipeline_and_cls(folder, config, custom_pipeline):\n custom_class_name = None\n if os.path.isfile(os.path.join(folder, f\"{custom_pipeline}.py\")):\n custom_pipeline = os.path.join(folder, f\"{custom_pipeline}.py\")\n elif isinstance(config[\"_class_name\"], (list, tuple)) and os.path.isfile(\n os.path.join(folder, f\"{config['_class_name'][0]}.py\")\n ):\n custom_pipeline = os.path.join(folder, f\"{config['_class_name'][0]}.py\")\n custom_class_name = config[\"_class_name\"][1]\n\n return custom_pipeline, custom_class_name\n```\n\nWhen `custom_class_name` is `None` (i.e. `custom_pipeline` was given as a kwarg rather than via the config), `_get_pipeline_class` will scan the file and automatically identify the class that subclasses `DiffusionPipeline`.\n\nOnce this is done, `_get_pipeline_class` is invoked with the resolved local path, which loads the custom code, retrieves the class object, and proceeds with instantiation.\n\n## The Vulnerability\n\n`_resolve_custom_pipeline_and_cls` receives `custom_pipeline` from the kwargs - when not supplied it defaults to `None`. That `None` is used in string formatting: `f\"{None}.py\"` = `\"None.py\"`.\n\n**If the repo contains a file with this name, it will be detected as a custom pipeline.**\n\nThis is only reached on the second invocation of `_get_pipeline_class` (inside `from_pretrained`, after `download()` returns). The trust\\_remote\\_code check lives entirely in `download()`, which evaluated `custom_pipeline is None -> False` and skipped it. By the time `_resolve_custom_pipeline_and_cls` runs, it is no longer relevant.\n\nAs a bonus, `None.py` even gets downloaded automatically when the model isn't cached yet. This isn't strictly required - it is quite plausible that the victim has already run `hf download <model>` and has all files locally - but if they haven't, revisiting the `allow_patterns` line above shows it makes the same error: `f\"{None}.py\"` = `\"None.py\"` is added to `allow_patterns` and fetched.\n\nWhat should `None.py` contain? To avoid breaking the pipeline load, it must define a class inheriting from `DiffusionPipeline`. To avoid leaving suspicious clues in the config, that class should shadow one that already exists in diffusers. The following satisfies both requirements:\n\n```python\nfrom diffusers import FluxPipeline as _FluxPipeline\n\nclass FluxPipeline(_FluxPipeline):\n pass\n\n# INSERT MALICIOUS CODE HERE\nimport pathlib\npathlib.Path(\"/tmp/pwned\").write_text(\":)\")\n```\n\nWith this, `model_index.json` can contain `\"_class_name\": \"FluxPipeline\"` - appearing to use the standard diffusers class - and the resulting pipeline is fully functional (it is also functional when running as a local directory). This has been verified against an extracted version of [DDUF/tiny-flux-dev-pipe-dduf](https://huggingface.co/DDUF/tiny-flux-dev-pipe-dduf).\n\nAll the attacker needs the victim to run is:\n\n```python\nfrom diffusers import DiffusionPipeline\n\npipeline = DiffusionPipeline.from_pretrained('ido-shani/none-py-trust-remote-code-bypass')\n```\n\n## PoC\n\n- Upload this zip as a model to the hub. https://drive.google.com/file/d/1mULARMLJJUTCi57xIv0wtDauko-JW0h7/view?usp=sharing\n- Run `DiffusionPipeline.from_pretrained` on the uploaded model hub identifier.\n- RCE occured; `/tmp/pwned` was created. If you are running the exploit on windows, change the path touched in `None.py`.\n\n# Impact\n\nThe vulnerability is a silent RCE - it allows arbitrary code to be loaded through the custom\\_pipeline flow from a Hub repo, with no `custom_pipeline` or `trust_remote_code` kwargs and nothing suspicious in the config. The `from_pretrained` call succeeds and returns a functional pipeline.\n\n# Occurrences\n\nhttps://github.com/huggingface/diffusers/blob/e1b5db52bda85d47a4f8f75954f77e672a8f7f1c/src/diffusers/pipelines/pipeline_loading_utils.py#L976\n\n# Patches\n\nYes. Fixed in **diffusers 0.38.0** via [PR #13448](https://github.com/huggingface/diffusers/pull/13448). All users on versions `< 0.38.0` should upgrade:\n\n```bash\npip install --upgrade \"diffusers>=0.38.0\"\n```\n\nThe fix moves the `trust_remote_code` gate out of `DiffusionPipeline.download()` and into `get_cached_module_file` in `src/diffusers/utils/dynamic_modules_utils.py`, which is the actual chokepoint for every dynamic module load (local, Hub, or community mirror). All three variants now raise `ValueError` when trust_remote_code=False instead of executing untrusted code. \n\n# Workarounds\n\nIf upgrading immediately is not possible:\n\n- Only call `from_pretrained` with `pretrained_model_name_or_path`, `custom_pipeline`, and local snapshot directories from sources you fully trust and have audited.\n- Do not pass `custom_pipeline=` pointing at a Hub repository different from the primary `pretrained_model_name_or_path` unless you have read its `pipeline.py`.\n- Before calling `from_pretrained` on a local snapshot, inspect the snapshot for unexpected `*.py` files, especially under component subdirectories (`unet/`, `scheduler/`, etc.) and at the snapshot root.\n\n# Why this should have a dedicated CVE\n\nGHSA-j7w6-vpvq-j3gm is a distinct defect from CVE-2026-44513. CVE-2026-44513 is a misplaced-security-gate bug requiring a user-supplied `custom_pipeline` argument or a config entry declaring custom code. GHSA-j7w6 is a string-formatting bug where the default custom_pipeline=None is interpolated into the filename `None.py`, allowing silent RCE on a fully default `from_pretrained('repo')` call with no kwargs and a `model_index.json` that shadows a legitimate class. The root cause root cause and trigger are different, although the fix applied to address CVE-2026-44513 also addresses this vulnerability.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "PyPI",
"name" : "diffusers"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "0.38.0"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/huggingface/diffusers/security/advisories/GHSA-j7w6-vpvq-j3gm"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-44827"
}, {
"type" : "WEB",
"url" : "https://github.com/huggingface/diffusers/pull/13448"
}, {
"type" : "WEB",
"url" : "https://github.com/huggingface/diffusers/commit/a37f6f8394ac2a7ee8360c3abea811efe54512b1"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/huggingface/diffusers"
}, {
"type" : "WEB",
"url" : "https://github.com/huggingface/diffusers/releases/tag/v0.38.0"
}, {
"type" : "WEB",
"url" : "https://github.com/pypa/advisory-database/tree/main/vulns/diffusers/PYSEC-2026-41.yaml"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-94" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-05-07T02:24:22Z",
"nvd_published_at" : "2026-05-14T17:16:23Z"
}
}