Skip to content

fix(dynamic_modules): enforce trust_remote_code for community pipeline branch#13742

Open
xodn348 wants to merge 1 commit into
huggingface:mainfrom
xodn348:fix/trust-remote-code-community-pipeline
Open

fix(dynamic_modules): enforce trust_remote_code for community pipeline branch#13742
xodn348 wants to merge 1 commit into
huggingface:mainfrom
xodn348:fix/trust-remote-code-community-pipeline

Conversation

@xodn348
Copy link
Copy Markdown

@xodn348 xodn348 commented May 13, 2026

What does this PR do?

The is_community_pipeline branch in get_cached_module_file() downloaded and executed Python code from diffusers/community-pipelines-mirror without checking trust_remote_code, while both the local-file branch and the HF Hub branch correctly gated on that flag. This made it possible for a user who set trust_remote_code=False (or relied on the default) to unknowingly load and execute remote community pipeline code.

The fix adds the same trust_remote_code guard to the community-pipeline branch that already exists for the other two branches. I also updated test_load_custom_github to (a) add a negative test confirming that loading without trust_remote_code=True now raises ValueError, and (b) pass trust_remote_code=True to the two existing positive-test calls.

Fixes #13691

Before submitting

Summary

The get_cached_module_file() function has three code paths — local file, community pipeline (short name, no /), and HF Hub repo. Both the local-file path and the HF Hub path guard on trust_remote_code and raise ValueError if it is False. The community-pipeline path skipped this check entirely, downloading and loading arbitrary Python from the diffusers/community-pipelines-mirror dataset regardless of what the user specified.

Root cause: the community-pipeline branch was added without carrying over the trust_remote_code guard that the other two branches already had. The mitigating factor (only loads from the official diffusers/community-pipelines-mirror dataset, not arbitrary user repos) does not remove the need for the flag: the whole point of trust_remote_code=False is to give users an opt-in gate for remote code execution, and community pipelines are remote code.

The fix adds a six-line if not trust_remote_code: raise ValueError(...) block at the top of the elif is_community_pipeline: branch, symmetric with the guards in the other two branches. The existing DIFFUSERS_DISABLE_REMOTE_CODE check at the start of the function already fires before all three branches, so that code path is unaffected.

Issue

Fixes #13691

Local verification

$ cd /tmp/diffusers
$ ruff check src/diffusers/utils/dynamic_modules_utils.py tests/pipelines/test_pipelines.py
All checks passed!
$ ruff format --check src/diffusers/utils/dynamic_modules_utils.py tests/pipelines/test_pipelines.py
2 files already formatted

# Unit tests for all three branches of the trust_remote_code logic
$ python -c "
import unittest.mock as mock, sys, os, tempfile
sys.path.insert(0, 'src')
from diffusers.utils.dynamic_modules_utils import get_cached_module_file

# 1. DIFFUSERS_DISABLE_REMOTE_CODE=True fires BEFORE the community-pipeline check
with mock.patch('diffusers.utils.dynamic_modules_utils.DIFFUSERS_DISABLE_REMOTE_CODE', True):
    try:
        get_cached_module_file('one_step_unet', 'pipeline.py', trust_remote_code=False)
        print('FAIL')
    except ValueError as e:
        print('PASS 1' if 'DIFFUSERS_DISABLE_REMOTE_CODE' in str(e) else 'FAIL')

# 2. community pipeline without trust_remote_code raises correct error
with mock.patch('diffusers.utils.dynamic_modules_utils.DIFFUSERS_DISABLE_REMOTE_CODE', False):
    try:
        get_cached_module_file('one_step_unet', 'pipeline.py', trust_remote_code=False)
        print('FAIL')
    except ValueError as e:
        ok = 'trust_remote_code=True' in str(e) and 'community pipeline' in str(e)
        print('PASS 2' if ok else 'FAIL')

# 3. local-file branch without trust_remote_code still raises
with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as f:
    f.write(b'# test'); tmpfile = f.name
try:
    with mock.patch('diffusers.utils.dynamic_modules_utils.DIFFUSERS_DISABLE_REMOTE_CODE', False):
        try:
            get_cached_module_file(os.path.dirname(tmpfile), os.path.basename(tmpfile), trust_remote_code=False)
            print('FAIL')
        except ValueError as e:
            print('PASS 3' if 'trust_remote_code=True' in str(e) else 'FAIL')
finally:
    os.unlink(tmpfile)
"
PASS 1
PASS 2
PASS 3

=== LOCAL_TEST_PASSED ===

Risk

The only behavior change is that DiffusionPipeline.from_pretrained(..., custom_pipeline="<short-name>") now raises ValueError if trust_remote_code is not True. Users who relied on community pipelines without opting in must add trust_remote_code=True — this is the same opt-in required for HF Hub custom pipelines. Existing users who already pass trust_remote_code=True are unaffected.

Who can review?

@DN6 @yiyixuxu (pipelines / dynamic-modules)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] Incomplete Fix for CVE-2026-44513: community Pipeline Branch Bypasses trust_remote_code Check

1 participant