modelscope / modelscope/ms-swift

Unauthenticated SSRF via multimodal image_url/audio/video in swift deploy (no URL filtering)

Open
#9,740 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
15.7k
Forks
1.7k
Avg merge
1d 16h
Merged PRs (30d)
136

Description

Checklist / 检查清单
  • I have searched existing issues, and this is a new bug report. / 我已经搜索过现有的 issues,确认这是一个新的 bug report。
Bug Description / Bug 描述

reported on 12 June 2026 https://github.com/modelscope/ms-swift/security/advisories/GHSA-7mpg-jvqj-ccxr

Summary

The ms-swift deployment server (swift deploy, OpenAI-compatible) fetches multimodal media URLs (image_url, audio_url, video_url) server-side with no validation of the target, and follows redirects. The server binds 0.0.0.0 and runs without authentication by default. An unauthenticated client of a multimodal deployment can therefore make the server issue requests to internal-only services and cloud instance-metadata endpoints. Confirmed against the load_file / load_image: the functions fetched an internal URL with no filter and followed a redirect.

Details

swift/template/vision_utils.py load_file (~line 141) fetches any http(s) path with no checks:

if path.startswith('http'):
    response = session.get(path, **request_kwargs)   # no scheme/IP filter; follows redirects

There is no loopback/private/link-local/metadata filtering anywhere in the function (no ipaddress, is_global, 127.0.0.1, localhost, 169.254, or allow_redirects handling). Reached via /v1/chat/completions: a message image_url.url is extracted in swift/template/template_inputs.py remove_messages_media (~line 127) into the images list, then swift/template/base.py load_image (~line 274) calls load_file. Defaults (swift/arguments/deploy_args.py): host='0.0.0.0' (~line 36), api_key=None (~line 38); swift/pipelines/infer/deploy.py _check_api_key (~line 116) passes when api_key is None. So the endpoint is unauthenticated and network-exposed by default.

How to Reproduce / 如何复现
PoC

scripts/poc_msswift_ssrf.md.

POST /v1/chat/completions
{"model":"<vl-model>","messages":[{"role":"user","content":[
  {"type":"image_url","image_url":{"url":"http://169.254.169.254/latest/meta-data/iam/security-credentials/"}}]}]}

Validated against the load_file / load_image: load_file("http://127.0.0.1:8456/secret.png") hit the local internal listener and returned the bytes (PNG magic confirmed); load_image decoded it; load_file("http://127.0.0.1:8456/redir") followed a 302 to /secret.png (so an attacker host can 302 to http://169.254.169.254/...). Source confirms no URL filter, default host 0.0.0.0, and api_key=None (no auth).

Impact

An unauthenticated client of a multimodal ms-swift deployment can coerce server-side requests to internal services and cloud instance-metadata endpoints (credential theft), and use redirects to reach metadata even if a host allowlist is later added. This is unauthenticated SSRF on the default configuration.

Additional Information / 补充信息

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with swift/template/vision_utils.py load_file and trace the media path through swift/template/template_inputs.py remove_messages_media and swift/template/base.py load_image. Review the defaults in swift/arguments/deploy_args.py and authentication flow in swift/pipelines/infer/deploy.py, then use scripts/poc_msswift_ssrf.md to reproduce the internal request and redirect behavior. Done means multimodal requests cannot reach protected internal targets through direct URLs or redirects.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.