Skip to content

fix(security): validate WeChat media URLs against CDN allowlist to prevent SSRF#9222

Closed
memosr wants to merge 1 commit into
NousResearch:mainfrom
memosr:fix/weixin-media-ssrf
Closed

fix(security): validate WeChat media URLs against CDN allowlist to prevent SSRF#9222
memosr wants to merge 1 commit into
NousResearch:mainfrom
memosr:fix/weixin-media-ssrf

Conversation

@memosr

@memosr memosr commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

gateway/platforms/weixin.py passed media URLs from the WeChat API
response directly to _download_bytes() without any validation:

# Before (vulnerable)
elif full_url:
    raw = await _download_bytes(session, url=full_url, ...)

full_url comes directly from the WeChat API JSON response. If the
API response is manipulated (MitM, compromised CDN, malicious bot
configuration), an attacker could redirect downloads to:

  • http://169.254.169.254/latest/meta-data/ → AWS IMDS
  • http://192.168.x.x/admin → internal network services
  • file:///etc/passwd → local file read

Fix

Added _WEIXIN_CDN_ALLOWLIST — a frozenset of known WeChat CDN
hostnames — and _assert_weixin_cdn_url() that validates every
media URL before download:

_WEIXIN_CDN_ALLOWLIST = frozenset({
    "novac2c.cdn.weixin.qq.com",
    "ilinkai.weixin.qq.com",
    "wx.qlogo.cn",
    "thirdwx.qlogo.cn",
    "res.wx.qq.com",
    "mmbiz.qpic.cn",
    "mmbiz.qlogo.cn",
})

Rejects non-http(s) schemes and hosts outside the allowlist with
a ValueError before any network request is made.

Type of Change

  • 🔒 Security fix (SSRF)

Checklist

  • Read the Contributing Guide
  • Commit messages follow Conventional Commits
  • Consistent with existing SSRF protection patterns in Hermes
  • No behavior change for legitimate WeChat CDN URLs

@teknium1

Copy link
Copy Markdown
Contributor

Merged as part of Batch-5 salvage: #11634

Your commit cherry-picked onto main with authorship preserved. The _WEIXIN_CDN_ALLOWLIST + _assert_weixin_cdn_url() check gives us defense in depth on the inbound media download path — complements the existing is_safe_url() check on the outbound _download_remote_media path. Runtime verified: the allowlist correctly rejects evil.com, file:// schemes, and unparseable URLs while passing legitimate WeChat CDN hosts. Thanks!

Commit SHA on main: cedc95c

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