{"record":{"id":"317561c0aafe8393","repo":"chenhg5/cc-connect","slug":"invalid-remote-image-url","errorCode":null,"errorMessage":"invalid remote image URL","messagePattern":"invalid remote image URL","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"platform/feishu/feishu.go","lineNumber":6585,"sourceCode":"\tu, err := url.Parse(rawURL)\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"\n}\n\nfunc richCardImageURLHost(rawURL string) string {\n\tu, err := url.Parse(rawURL)\n\tif err != nil || u.Host == \"\" {\n\t\treturn \"\"\n\t}\n\treturn u.Hostname()\n}\n\nfunc fetchRichCardRemoteImage(ctx context.Context, rawURL string) ([]byte, string, error) {\n\tu, err := url.Parse(rawURL)\n\tif err != nil || (u.Scheme != \"http\" && u.Scheme != \"https\") || u.Host == \"\" {\n\t\treturn nil, \"\", errors.New(\"invalid remote image URL\")\n\t}\n\n\tclient := &http.Client{\n\t\tTimeout: richCardImageFinalWait,\n\t\tTransport: &http.Transport{\n\t\t\tDialContext:           dialPublicRichCardImageContext,\n\t\t\tResponseHeaderTimeout: richCardImageFinalWait,\n\t\t},\n\t\tCheckRedirect: func(req *http.Request, via []*http.Request) error {\n\t\t\tif len(via) >= 3 {\n\t\t\t\treturn errors.New(\"too many redirects\")\n\t\t\t}\n\t\t\tif !isRemoteRichCardImageURL(req.URL.String()) {\n\t\t\t\treturn errors.New(\"redirected to unsupported image URL\")\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}","sourceCodeStart":6567,"sourceCodeEnd":6603,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L6567-L6603","documentation":"fetchRichCardRemoteImage validates the supplied URL before fetching an image for a rich Feishu card. It parses the URL and requires an http/https scheme and a non-empty host; anything else returns this error without any network activity. This guards against malformed input and non-HTTP schemes (file:, data:, ftp:) being used for SSRF or file access.","triggerScenarios":"A rich card image URL fails url.Parse, has a scheme other than http/https (e.g. ftp://, file://, data:), or lacks a host (protocol-relative malformed input) — checked at platform/feishu/feishu.go:6585.","commonSituations":"Agent output embeds a data: URI or relative path as an image URL; markdown image link is malformed or missing scheme; config/content supplies \"localhost-only\" style URLs without a proper host part; typos like htp://.","solutions":["Fix the source URL to be an absolute http(s) URL with a valid host.","Upload local/data-URI images through Feishu's image upload API instead of a remote URL.","Validate image URLs (scheme + host) before embedding them in card content."],"exampleFix":"// before\ncard.ImageURL = \"data:image/png;base64,iVBOR...\"\n// after\n// upload data URI bytes via Feishu image API and use the returned image_key\ncard.ImageKey = uploadFeishuImage(ctx, dataURIBytes)","handlingStrategy":"validation","validationCode":"u, err := url.Parse(rawURL)\nvalid := err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"","typeGuard":"func isFetchableImageURL(raw string) bool {\n    u, err := url.Parse(raw)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"\n}","tryCatchPattern":"data, mime, err := fetchRichCardRemoteImage(ctx, rawURL)\nif err != nil {\n    // fall back to placeholder card or upload-through-API path\n}","preventionTips":["Normalize agent/model output: convert data: URIs to uploaded image keys before card assembly.","Sanitize image URLs at message-ingestion time, not at send time.","Maintain an allowlist of schemes for any remotely referenced media."],"tags":["feishu","url","validation","cards","image"],"backgroundTag":"invalid-url","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}