Skip to content

fix(websearch): block non-public URLs in page fetching - #1020

Open
SiyuanChenToDo wants to merge 1 commit into
modelscope:mainfrom
SiyuanChenToDo:fix/block-non-public-fetch-urls
Open

SiyuanChenToDo wants to merge 1 commit into
modelscope:mainfrom
SiyuanChenToDo:fix/block-non-public-fetch-urls

Conversation

@SiyuanChenToDo

Copy link
Copy Markdown

Summary

WebSearchTool.fetch_page accepted arbitrary model-supplied URLs and passed
them to Jina Reader, the direct urllib fallback, and the Playwright fallback
without restricting the destination. This allowed SSRF against loopback,
RFC1918, link-local, multicast, and cloud-metadata addresses (for example
169.254.169.254 and 100.100.100.200), and redirects were followed without
re-validation.

This adds ms_agent/tools/url_safety.py:

  • accepts only http/https URLs with a hostname;
  • resolves the hostname and rejects the request if any resolved address is
    loopback, private, link-local, multicast, reserved, unspecified, or
    otherwise non-global;
  • unwraps IPv4-mapped IPv6 addresses and strips IPv6 zone IDs;
  • rejects known metadata hostnames and .localhost / .local / .internal
    suffixes;
  • re-validates every redirect target in the urllib opener.

The check runs before Jina Reader, before the direct HTTP fallback, and on
every document navigation in the Playwright fallback, so a public URL cannot
redirect into an internal one. ContentFetcher now documents that local
fetchers must enforce this.

Fixes #1018

Test

  • pytest tests/tools/test_url_safety.py tests/tools/test_server_tools_smoke.py -q — 41 passed, 3 skipped
  • flake8 / yapf 0.32 / py_compile on changed files — passed
  • Reverting the Jina validation makes the regression test fail
  • New tests cover private IPv4/IPv6 ranges, IPv4-mapped loopback, mixed
    public/private DNS answers, metadata addresses, redirects, and the
    Jina/Playwright entry points

AI assistance

Prepared with AI assistance (Claude Code); I reviewed the diff, ran the tests,
and can explain and defend the change.

fetch_page accepted arbitrary model-supplied URLs and passed them to Jina Reader, the direct urllib fallback, and the Playwright fallback without restricting the destination. Resolve hostnames and reject loopback, private, link-local, multicast, reserved, and cloud-metadata addresses; re-validate every HTTP redirect; and re-check document navigations in the Playwright fallback.

Fixes modelscope#1018

Co-Authored-By: Claude Code <noreply@anthropic.com>

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.

fetch_page web tool performs unrestricted server-side HTTP fetch of agent-supplied URLs (SSRF)

1 participant