Fix several security issues. by Vancir · Pull Request #1759 · modelscope/modelscope · GitHub
Skip to content

Fix several security issues. - #1759

Open
Vancir wants to merge 1 commit into
modelscope:masterfrom
Vancir:master
Open

Vancir wants to merge 1 commit into
modelscope:masterfrom
Vancir:master

Conversation

@Vancir

@Vancir Vancir commented Jul 20, 2026

Copy link
Copy Markdown

Security: fix multiple RCE vectors in ModelScope

This PR fixes a cluster of remote-code-execution bugs where attacker-controlled
artifacts (model repo files) were fed unchecked to create_model, load_model_from_config,
or unsafe YAML loaders.

  1. Issue Remote code execution via unsafe yaml loading #1660 — RCE via unsafe yaml loading
  • use yaml.SafeLoader rather than unsafe yaml.Loader
  1. Issue Remote code execution via ImageViewTransform during model loading #1659 — RCE via ImageViewTransform
  • add check_trust_remote_code() before load_model_from_config.
  1. Issue Remote Code Execution via unsafe YAML-based dynamic instantiation in ControlNet and StablediffusionPaintbyexample #1758 - RCE via ControlNet and StablediffusionPaintbyexample
  • add check_trust_remote_code() before load_model_from_config.
  • add check_trust_remote_code() before create_model.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves security by switching from unsafe YAML loading to yaml.SafeLoader and adding or reordering check_trust_remote_code checks before loading configurations. The review feedback recommends using the more idiomatic and concise yaml.safe_load function instead of explicitly passing Loader=yaml.SafeLoader. Additionally, it is advised to call check_trust_remote_code at the very beginning of initialization methods to ensure no untrusted files are parsed beforehand.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

Calling self.check_trust_remote_code(model_dir=model_dir) at the very beginning of __init__ (right after super().__init__) is safer and more robust. This ensures that any configuration loading (such as Config.from_file on line 42) or parameter parsing from the untrusted model directory is gated by the trust check, preventing potential exploitation of parser vulnerabilities or unnecessary processing of untrusted input.

Comment on lines 43 to +44
config = OmegaConf.load(os.path.join(model_dir, 'v1.yaml'))
self.check_trust_remote_code(model_dir=model_dir)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

Calling self.check_trust_remote_code(model_dir=model_dir) before loading the configuration file (v1.yaml) via OmegaConf.load is safer. This ensures that no files from the untrusted model directory are parsed or loaded before verifying that the remote code/repository is trusted.

Suggested change
config = OmegaConf.load(os.path.join(model_dir, 'v1.yaml'))
self.check_trust_remote_code(model_dir=model_dir)
self.check_trust_remote_code(model_dir=model_dir)
config = OmegaConf.load(os.path.join(model_dir, 'v1.yaml'))

Comment on lines +170 to +172
self.am_config = yaml.load(f, Loader=yaml.SafeLoader)
with open(self.voc_config_path, 'r') as f:
self.voc_config = yaml.load(f, Loader=yaml.Loader)
self.voc_config = yaml.load(f, Loader=yaml.SafeLoader)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using yaml.safe_load(f) is more idiomatic, cleaner, and less verbose than yaml.load(f, Loader=yaml.SafeLoader) while providing the same security guarantees.

Suggested change
self.am_config = yaml.load(f, Loader=yaml.SafeLoader)
with open(self.voc_config_path, 'r') as f:
self.voc_config = yaml.load(f, Loader=yaml.Loader)
self.voc_config = yaml.load(f, Loader=yaml.SafeLoader)
self.am_config = yaml.safe_load(f)
with open(self.voc_config_path, 'r') as f:
self.voc_config = yaml.safe_load(f)

Comment on lines +369 to +371
config = yaml.load(f, Loader=yaml.SafeLoader)
with open(config_path, 'r') as f:
config.update(yaml.load(f, Loader=yaml.Loader))
config.update(yaml.load(f, Loader=yaml.SafeLoader))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using yaml.safe_load(f) is more idiomatic, cleaner, and less verbose than yaml.load(f, Loader=yaml.SafeLoader) while providing the same security guarantees.

Suggested change
config = yaml.load(f, Loader=yaml.SafeLoader)
with open(config_path, 'r') as f:
config.update(yaml.load(f, Loader=yaml.Loader))
config.update(yaml.load(f, Loader=yaml.SafeLoader))
config = yaml.safe_load(f)
with open(config_path, 'r') as f:
config.update(yaml.safe_load(f))

Comment on lines +532 to +535
config = yaml.load(f, Loader=yaml.SafeLoader)

with open(config_path, 'r') as f:
config.update(yaml.load(f, Loader=yaml.Loader))
config.update(yaml.load(f, Loader=yaml.SafeLoader))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using yaml.safe_load(f) is more idiomatic, cleaner, and less verbose than yaml.load(f, Loader=yaml.SafeLoader) while providing the same security guarantees.

Suggested change
config = yaml.load(f, Loader=yaml.SafeLoader)
with open(config_path, 'r') as f:
config.update(yaml.load(f, Loader=yaml.Loader))
config.update(yaml.load(f, Loader=yaml.SafeLoader))
config = yaml.safe_load(f)
with open(config_path, 'r') as f:
config.update(yaml.safe_load(f))

os.PathLike]) -> Dict[str, Any]:
with open(yaml_file, 'r', encoding='utf-8') as reader:
config_dict = yaml.load(reader, Loader=yaml.Loader)
config_dict = yaml.load(reader, Loader=yaml.SafeLoader)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using yaml.safe_load(reader) is more idiomatic, cleaner, and less verbose than yaml.load(reader, Loader=yaml.SafeLoader) while providing the same security guarantees.

Suggested change
config_dict = yaml.load(reader, Loader=yaml.SafeLoader)
config_dict = yaml.safe_load(reader)

os.PathLike]) -> Dict[str, Any]:
with open(yaml_file, 'r', encoding='utf-8') as reader:
config_dict = yaml.load(reader, Loader=yaml.Loader)
config_dict = yaml.load(reader, Loader=yaml.SafeLoader)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using yaml.safe_load(reader) is more idiomatic, cleaner, and less verbose than yaml.load(reader, Loader=yaml.SafeLoader) while providing the same security guarantees.

Suggested change
config_dict = yaml.load(reader, Loader=yaml.SafeLoader)
config_dict = yaml.safe_load(reader)

@mtholmquist

Copy link
Copy Markdown

Thanks for tackling these — switching the yaml.Loader calls in voice.py and configuration_mplug.py to SafeLoader is the correct fix.

For the record and to help with tracking: I independently reported these same sinks (the sambert TTS Voice.__init__ acoustic/vocoder config loads and the MPlug config loads) through GitHub's private vulnerability reporting on 2026-07-07 — advisory GHSA-7629-4rmx-r5c4 — about two weeks before this PR was opened. They remain exploitable on the latest release (1.39.1) and the v1.40.0 tag: a model config YAML carrying a !!python/object/apply:... tag runs arbitrary code on load, since yaml.Loader honors those tags with no trust_remote_code gate.

Could a maintainer link this PR to GHSA-7629-4rmx-r5c4 and publish the advisory (with a CVE) when it merges? I'm glad to help with the advisory metadata — the affected range should read <= 1.39.1, not the draft's <= 1.38.1. Thanks again.

@Vancir

Vancir commented Aug 28, 2026

Copy link
Copy Markdown
Author

I reported the unsafe YAML deserialization about 10 months ago (#1538, #1540). It takes the maintainers long time to handle these issues, so I had to create a PR to shorten the fix cycle.

@github-actions

Copy link
Copy Markdown

This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.

@github-actions github-actions Bot added the Stale label Oct 13, 2026
@Vancir

Vancir commented Oct 13, 2026

Copy link
Copy Markdown
Author

@github-actions github-actions Bot removed the Stale label Oct 14, 2026

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants