Tencent/WeKnora · error
invalid qqbot api_base_url: %w (for private deployments, add
Error message
invalid qqbot api_base_url: %w (for private deployments, add the hostname to SSRF_WHITELIST)
What it means
The QQ bot client validates its HTTP API base URL for SSRF before use. If secutils.ValidateURLForSSRF rejects the host, NewClient fails with this wrapped error explaining how to allow private deployments. This protects against using the bot credentials to reach internal services.
Source
Thrown at internal/im/qqbot/client.go:87
if result.URL == "" {
return "", fmt.Errorf("empty qqbot gateway url")
}
if err := validateGatewayURL(result.URL); err != nil {
return "", fmt.Errorf("invalid qqbot gateway url: %w", err)
}
return result.URL, nil
}
func validateHTTPAPIBaseURL(raw string) error {
u, err := url.Parse(raw)
if err != nil || u.Host == "" {
return fmt.Errorf("invalid qqbot api_base_url: must be a valid http(s) URL")
}
if u.Scheme != "http" && u.Scheme != "https" {
return fmt.Errorf("invalid qqbot api_base_url: must use http or https")
}
if err := secutils.ValidateURLForSSRF(raw); err != nil {
return fmt.Errorf("invalid qqbot api_base_url: %w (for private deployments, add the hostname to SSRF_WHITELIST)", err)
}
return nil
}
func validateGatewayURL(raw string) error {
if strings.TrimSpace(raw) == "" {
return nil
}
u, err := url.Parse(raw)
if err != nil || u.Host == "" {
return fmt.Errorf("gateway_url must be a valid wss URL")
}
if u.Scheme != "wss" {
return fmt.Errorf("gateway_url must use wss")
}
checkURL := *u
checkURL.Scheme = "https"
if err := secutils.ValidateURLForSSRF(checkURL.String()); err != nil {View on GitHub (pinned to 988cbb0330)
Solutions
- Add the hostname to the SSRF_WHITELIST environment variable
- Use the official QQ bot API base URL (https://api.sgroup.qq.com)
- Verify api_base_url parses as a valid http(s) URL with a public host
Example fix
// before client, err := NewClient(cfg) // api_base_url: http://qqbot-proxy.internal // after // export SSRF_WHITELIST=qqbot-proxy.internal client, err := NewClient(cfg)
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(cfg.APIBaseURL)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") || u.Host == "" {
return fmt.Errorf("invalid qqbot api_base_url: %q", cfg.APIBaseURL)
} Try / catch
client, err := NewClient(cfg)
if err != nil && strings.Contains(err.Error(), "SSRF_WHITELIST") {
return fmt.Errorf("qqbot api host blocked: %w", err)
} Prevention
- Use the official QQ API base URL by default
- List private hosts in SSRF_WHITELIST only when self-hosting
- Add config validation before client construction
When it happens
Trigger: NewClient is called with an api_base_url whose hostname is private/loopback/otherwise SSRF-blocked and not in SSRF_WHITELIST.
Common situations: Pointing the client at an internal QQ bot proxy or mock server; localhost in development; SSRF_WHITELIST missing from the container/deployment env.
Related errors
- unsafe MinIO endpoint: %w
- unsafe TOS endpoint: %w
- %w (for private deployments on internal networks, add the ho
- gateway_url failed SSRF validation: %w (for private deployme
- MinerU URL blocked by SSRF check: %v
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/56c143fe62425249.
Report an issue: GitHub.