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
- Add the deployment hostname to the SSRF_WHITELIST environment variable
- If targeting public Feishu, remove or fix the custom api_base_url so it uses the official https://open.feishu.cn endpoint
- 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
- Keep the official Feishu endpoint unless you truly self-host
- Document SSRF_WHITELIST in deployment env templates
- Pre-flight the base URL in config tests
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
- unsafe MinIO endpoint: %w
- unsafe TOS endpoint: %w
- invalid qqbot api_base_url: %w (for private deployments, add
- MinerU URL blocked by SSRF check: %v
- unsafe OSS endpoint: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/53a7545e3cda170d.
Report an issue: GitHub.