{"record":{"id":"a52eecd040e41fd5","repo":"Tencent/WeKnora","slug":"w-invalid-scheme-s","errorCode":null,"errorMessage":"%w: invalid scheme %s","messagePattern":"%w: invalid scheme (.+?)","errorType":"http","errorClass":"ErrSSRFRedirectBlocked","httpStatus":null,"severity":"error","filePath":"internal/utils/security.go","lineNumber":721,"sourceCode":"// every redirect target against SSRF protections.\nfunc newSSRFCheckRedirect(maxRedirects int) func(*http.Request, []*http.Request) error {\n\treturn func(req *http.Request, via []*http.Request) error {\n\t\t// Check redirect count\n\t\tif len(via) >= maxRedirects {\n\t\t\treturn fmt.Errorf(\"stopped after %d redirects\", maxRedirects)\n\t\t}\n\n\t\t// Strip credentials when the redirect crosses hosts so connector\n\t\t// tokens (e.g. Yuque X-Auth-Token) cannot leak to a third party.\n\t\tif len(via) > 0 && !sameHTTPOrigin(via[0].URL, req.URL) {\n\t\t\tstripRedirectSensitiveHeaders(req)\n\t\t}\n\n\t\t// Validate the redirect target URL for SSRF (whitelist-aware).\n\t\t// Even whitelisted hosts must use http/https to prevent scheme-based attacks.\n\t\tredirectScheme := strings.ToLower(req.URL.Scheme)\n\t\tif redirectScheme != \"http\" && redirectScheme != \"https\" {\n\t\t\treturn fmt.Errorf(\"%w: invalid scheme %s\", ErrSSRFRedirectBlocked, redirectScheme)\n\t\t}\n\t\tredirectHost := req.URL.Hostname()\n\t\tif redirectHost != \"\" && IsSSRFWhitelisted(redirectHost) {\n\t\t\treturn nil\n\t\t}\n\t\tif err := validateURLForSSRFForOutbound(req.URL.String()); err != nil {\n\t\t\treturn fmt.Errorf(\"%w: %w\", ErrSSRFRedirectBlocked, err)\n\t\t}\n\n\t\treturn nil\n\t}\n}\n\n// SSRFValidatingRoundTripper enforces the URL policy for every outbound\n// request, including URLs discovered at runtime by SDKs (for example OAuth\n// metadata) that never passed through an application handler. Dial-time checks\n// remain necessary to pin DNS answers and cover transports that cannot accept\n// this wrapper directly.","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/utils/security.go#L703-L739","documentation":"A redirect target used a URL scheme other than http or https (e.g. file:, gopher:, ftp:). The redirect policy wraps ErrSSRFRedirectBlocked with 'invalid scheme %s' because even whitelisted hosts must use http/https, blocking scheme-based attacks during redirect following.","triggerScenarios":"A server responds with a Location header whose scheme is not http/https while the client follows redirects through newSSRFCheckRedirect.","commonSituations":"Malicious or buggy servers emitting 'Location: file:///etc/passwd' or custom-scheme redirects; attacker-controlled endpoints attempting to pivot the client away from HTTP.","solutions":["errors.Is(err, secutils.ErrSSRFRedirectBlocked) will match — handle it as a blocked redirect and stop.","Only follow redirects from trusted servers; never point the client at untrusted endpoints that control Location.","Ensure the upstream URL you call is https so any redirect it issues stays in-scheme.","Check the server's Location header construction for a bug producing a bad scheme."],"exampleFix":"// before\nresp, err := client.Do(req) // server redirects to file://...\n// after\nif errors.Is(err, secutils.ErrSSRFRedirectBlocked) {\n    log.Printf(\"refusing redirect: %v\", err) // inspect/fix upstream Location scheme\n}","handlingStrategy":"try-catch","validationCode":"if u.Scheme != \"http\" && u.Scheme != \"https\" { return fmt.Errorf(\"unsupported scheme: %s\", u.Scheme) }","typeGuard":"func isBlockedRedirectScheme(err error) bool {\n    return errors.Is(err, secutils.ErrSSRFRedirectBlocked)\n}","tryCatchPattern":"if errors.Is(err, secutils.ErrSSRFRedirectBlocked) {\n    log.Printf(\"redirect rejected (check scheme/Location): %v\", err)\n    return err\n}","preventionTips":["Only call trusted servers that emit http(s) Location headers.","Start from https URLs so redirects stay in-scheme.","Never let fully attacker-controlled endpoints drive your redirect chain."],"tags":["security","ssrf","http","redirect","scheme"],"backgroundTag":"ssrf-redirect-blocked","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}