Tencent/WeKnora · error

gateway_url failed SSRF validation: %w (for private deployme

Error message

gateway_url failed SSRF validation: %w (for private deployments, add the hostname to SSRF_WHITELIST)

What it means

The gateway host is SSRF-checked by rewriting the wss URL to https and running secutils.ValidateURLForSSRF. Blocked hosts (private IPs, loopback, etc.) fail NewClient/GatewayURL with this wrapped error, which explains the SSRF_WHITELIST opt-in.

Source

Thrown at internal/im/qqbot/client.go:106

	}
	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 {
		return fmt.Errorf(
			"gateway_url failed SSRF validation: %w (for private deployments, add the hostname to SSRF_WHITELIST)",
			err,
		)
	}
	return nil
}

func (c *Client) SendC2CMessage(ctx context.Context, openID, content, msgID string) error {
	path := fmt.Sprintf("/v2/users/%s/messages", openID)
	return c.sendText(ctx, path, content, msgID)
}

func (c *Client) SendGroupMessage(ctx context.Context, groupOpenID, content, msgID string) error {
	path := fmt.Sprintf("/v2/groups/%s/messages", groupOpenID)
	return c.sendText(ctx, path, content, msgID)
}

func (c *Client) sendText(ctx context.Context, path, content, msgID string) error {

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Add the gateway hostname to the SSRF_WHITELIST environment variable
  2. Use the official wss gateway endpoint
  3. Confirm the hostname resolves publicly if you expected it to pass

Example fix

// before
GATEWAY_URL=wss://gw.internal:8080/ws  // rejected
// after
// export SSRF_WHITELIST=gw.internal
GATEWAY_URL=wss://gw.internal:8080/ws
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(cfg.GatewayURL)
if err == nil && u.Host != "" {
    httpsURL := *u
    httpsURL.Scheme = "https"
    _ = httpsURL // run your own SSRF check or ensure host is in SSRF_WHITELIST
}

Try / catch

client, err := NewClient(cfg)
if err != nil && strings.Contains(err.Error(), "SSRF_WHITELIST") {
    return fmt.Errorf("gateway host blocked by SSRF guard: %w", err)
}

Prevention

When it happens

Trigger: gateway_url points at a private/loopback/blocked hostname and SSRF_WHITELIST does not include it.

Common situations: Self-hosted or proxied QQ gateway on an internal network; local gateway in development; SSRF_WHITELIST not propagated to the running process.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/d580ce8959927422. Report an issue: GitHub.