Skip to content

Bug: QQBot plugin token/API requests blocked by SSRF guard in fake-IP proxy environments (Surge/Clash) #70310

@colin-chang

Description

@colin-chang

Bug Description

QQBot plugin fails to obtain access tokens and make API requests when running behind a fake-IP proxy (e.g., Surge, Clash). The SSRF guard blocks requests because DNS resolves to the RFC 2544 benchmark range (198.18.0.0/15) used by fake-IP proxies.

Error Log

[security] blocked URL fetch (qqbot.token) target=https://bots.qq.com/app/getAppAccessToken reason=Blocked: resolves to private/internal/special-use IP address
[qqbot] [qqbot:default] Connection failed: Network error getting access_token: Blocked: resolves to private/internal/special-use IP address

This repeats every ~30s for all QQBot instances.

Root Cause

In extensions/qqbot/api-*.js, the fetchWithSsrFGuard calls for token fetching and API requests are missing the ssrfPolicy parameter:

Token request (doFetchToken):

const guarded = await fetchWithSsrFGuard({
    url: TOKEN_URL,
    init: { method: "POST", headers, body },
    auditContext: "qqbot.token"
    // ❌ Missing: ssrfPolicy
});

API request (apiRequest):

const guarded = await fetchWithSsrFGuard({
    url,
    init: options,
    auditContext: `qqbot.api${path}`
    // ❌ Missing: ssrfPolicy
});

Meanwhile, the media download path correctly includes SSRF policy with allowRfc2544BenchmarkRange: true:

const QQBOT_MEDIA_SSRF_POLICY = {
    hostnameAllowlist: [
        "*.qpic.cn", "*.qq.com", "*.weiyun.com", "*.qq.com.cn",
        "*.ugcimg.cn", "*.myqcloud.com", "*.tencentcos.cn", "*.tencentcos.com"
    ],
    allowRfc2544BenchmarkRange: true  // ✅ Correctly handles fake-IP proxies
};

Environment

  • macOS with Surge proxy (fake-ip mode)
  • dns.lookup("bots.qq.com") returns 198.18.35.155 (fake-IP)
  • dns.resolve4("bots.qq.com") returns 183.47.104.95 (real IP)
  • OpenClaw v2026.4.21

Workaround

Patching api-*.js to add ssrfPolicy to the two fetchWithSsrFGuard calls:

const guarded = await fetchWithSsrFGuard({
    url: TOKEN_URL,
    init: { ... },
    auditContext: "qqbot.token",
    policy: {
        hostnameAllowlist: ["*.qq.com"],
        allowRfc2544BenchmarkRange: true
    }
});

This works but will be overwritten on upgrade.

Expected Fix

Apply the same QQBOT_MEDIA_SSRF_POLICY (or a similar policy) to token and API requests in the QQBot plugin, since all QQBot API endpoints are under *.qq.com and need the same fake-IP proxy compatibility that media downloads already have.

Related

The Telegram plugin already handles this scenario via dangerouslyAllowPrivateNetwork. The QQBot plugin should have equivalent support for fake-IP proxy environments.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions