Tencent/WeKnora · error
invalid scheme: %s (only http/https allowed)
Error message
invalid scheme: %s (only http/https allowed)
What it means
ValidateURLForSSRF only permits http and https schemes. Any other scheme — file://, gopher://, ftp://, dict://, ldap:// — is rejected with 'invalid scheme'. This is a core SSRF defense: a whitelist relaxes host/IP restrictions only and must never legitimize dangerous non-HTTP schemes that can reach local files or internal services.
Source
Thrown at internal/utils/security.go:1205
if !strings.Contains(normalized, "://") {
normalized = "https://" + normalized
}
parsed, err := url.Parse(normalized)
if err != nil {
return fmt.Errorf("invalid URL: %w", err)
}
hostname := parsed.Hostname()
if hostname == "" {
return fmt.Errorf("URL has no hostname")
}
// A whitelist relaxes host/IP restrictions only. It must never turn other
// schemes (file://, gopher://, etc.) into valid outbound request targets.
scheme := strings.ToLower(parsed.Scheme)
if scheme != "http" && scheme != "https" {
return fmt.Errorf("invalid scheme: %s (only http/https allowed)", scheme)
}
// If the host is whitelisted, skip the heavy checks.
if IsSSRFWhitelisted(hostname) {
return nil
}
// Delegate to the full SSRF validation (uses the normalised URL).
if safe, reason := isSSRFSafeURL(normalized); !safe {
return fmt.Errorf("SSRF validation failed: %s", reason)
}
return nil
}
// IsSystemProxy 判断是否为系统代理
func IsSystemProxy(host string) bool {
proxyCfg := httpproxy.FromEnvironment()
for _, proxyUrl := range []string{View on GitHub (pinned to 988cbb0330)
Solutions
- Use https:// (or http:// for explicitly internal/trusted endpoints) as the URL scheme
- Do not use the storage client for local file access — read files directly with os.Open instead
- Verify the endpoint config value wasn't accidentally prefixed with the wrong scheme
- Note the scheme check is case-insensitive (HTTP:// is fine); the scheme itself is the problem, not casing
Example fix
// before endpoint := "file:///data/export" client, err := newOSSClient(endpoint, ...) // after endpoint := "https://oss.example.com" client, err := newOSSClient(endpoint, ...)
Defensive patterns
Strategy: validation
Validate before calling
n := endpoint
if !strings.Contains(n, "://") { n = "https://" + n }
u, err := url.Parse(n)
if err != nil {
return err
}
s := strings.ToLower(u.Scheme)
if s != "http" && s != "https" {
return fmt.Errorf("scheme %q not allowed; use http/https", s)
} Type guard
func isHTTPScheme(raw string) bool {
if !strings.Contains(raw, "://") { raw = "https://" + raw }
u, err := url.Parse(raw)
return err == nil && (strings.EqualFold(u.Scheme, "http") || strings.EqualFold(u.Scheme, "https"))
} Prevention
- Only point storage clients at http(s) endpoints
- Use os/io APIs for local files, never file:// through a storage client
- Whitelists do not relax the scheme check — fix the scheme itself
- Sanitize any user-supplied URL before it reaches ValidateURLForSSRF
When it happens
Trigger: A storage endpoint or connectivity-check URL uses a non-http(s) scheme, e.g. 'file:///etc/passwd', 'gopher://127.0.0.1:70', 'ftp://files.example.com', passed to newS3Client, newOSSClient, newMinioClient, newKS3Client, NewObsFileService, or CheckObsConnectivity.
Common situations: Attempting to point a storage client at a local file path, copying a non-HTTP service URL into the endpoint config, or an attacker-controlled URL reaching the validation function during an SSRF probe.
Related errors
- URL rejected: %w
- base_url SSRF validation failed: %w
- URL rejected for security reasons: %v
- docreader address failed SSRF validation: %w
- blocked by SSRF policy: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/057df1d8420bf887.
Report an issue: GitHub.