Tencent/WeKnora · error

%w (for private deployments on internal networks, add the ho

Error message

%w (for private deployments on internal networks, add the hostname to SSRF_WHITELIST)

What it means

validateAPIBaseURL rejects a configured Feishu api_base_url whose hostname fails SSRF validation (private/loopback/link-local addresses). The library enforces this to prevent server-side request forgery against internal networks. The wrapped error tells you how to opt in for legitimate private deployments.

Source

Thrown at internal/im/feishu/adapter.go:106

}

// validateAPIBaseURL checks that a custom Feishu/Lark API base URL uses an
// http(s) scheme and passes SSRF validation. Empty or the region default is
// allowed without further checks. Mirrors wecom.validateEndpointURL but allows
// plain http for internal-network reverse proxies that terminate TLS at nginx.
func validateAPIBaseURL(endpoint, defaultEndpoint string) error {
	if endpoint == "" || endpoint == defaultEndpoint {
		return nil
	}
	u, err := url.Parse(endpoint)
	if err != nil {
		return fmt.Errorf("invalid api_base_url: %w", err)
	}
	if u.Scheme != "http" && u.Scheme != "https" {
		return fmt.Errorf("api_base_url must use http(s):// scheme, got %s://", u.Scheme)
	}
	if err := utils.ValidateURLForSSRF(endpoint); err != nil {
		return fmt.Errorf("%w (for private deployments on internal networks, add the hostname to SSRF_WHITELIST)", err)
	}
	return nil
}

// api builds an Open Platform API URL on this adapter's cloud. path is a format
// string beginning with "/open-apis/"; args fill its verbs.
func (a *Adapter) api(path string, args ...any) string {
	return a.apiBaseURL + fmt.Sprintf(path, args...)
}

// startStreamReaper starts a background goroutine (once) that periodically
// removes orphaned stream entries from feishuStreams. This prevents memory
// leaks when EndStream is never called due to panics or pipeline errors.
func startStreamReaper() {
	startReaperOnce.Do(func() {
		go func() {
			ticker := time.NewTicker(streamReaperInterval)
			defer ticker.Stop()

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Add the deployment hostname to the SSRF_WHITELIST environment variable
  2. If targeting public Feishu, remove or fix the custom api_base_url so it uses the official https://open.feishu.cn endpoint
  3. Ensure api_base_url is a valid http(s) URL pointing at a public host

Example fix

// before
adapter, err := NewAdapter(ctx, cfg) // api_base_url: http://feishu.internal
// after
// set SSRF_WHITELIST=feishu.internal in the environment, or:
cfg.APIBaseURL = "https://open.feishu.cn"
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(cfg.APIBaseURL)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
    return fmt.Errorf("bad api_base_url: %q", cfg.APIBaseURL)
}
// ensure host is public or listed in SSRF_WHITELIST before constructing

Try / catch

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

Prevention

When it happens

Trigger: NewAdapter is constructed with an api_base_url pointing at a private IP, localhost, or other SSRF-blocked host (e.g. self-hosted Feishu on 10.x/192.168.x/internal DNS), and the hostname is not listed in SSRF_WHITELIST.

Common situations: Self-hosting against an internal Feishu/Lark deployment; pointing api_base_url at localhost in development; DNS resolving to an internal address; SSRF_WHITELIST env var not set in the deployment environment.

Related errors


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