{"record":{"id":"28170aa7f9ce7333","repo":"usememos/memos","slug":"wrong-image-mediatype","errorCode":null,"errorMessage":"wrong image mediatype","messagePattern":"wrong image mediatype","errorType":"http","errorClass":null,"httpStatus":null,"severity":"info","filePath":"internal/httpgetter/image.go","lineNumber":32,"sourceCode":"}\n\nfunc GetImage(urlStr string) (*Image, error) {\n\tif _, err := url.Parse(urlStr); err != nil {\n\t\treturn nil, err\n\t}\n\n\tresponse, err := http.Get(urlStr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer response.Body.Close()\n\n\tmediatype, err := getMediatype(response)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !strings.HasPrefix(mediatype, \"image/\") {\n\t\treturn nil, errors.New(\"wrong image mediatype\")\n\t}\n\n\tbodyBytes, err := io.ReadAll(response.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\timage := &Image{\n\t\tBlob:      bodyBytes,\n\t\tMediatype: mediatype,\n\t}\n\treturn image, nil\n}\n","sourceCodeStart":14,"sourceCodeEnd":46,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/internal/httpgetter/image.go#L14-L46","documentation":"The image getter in internal/httpgetter downloaded the URL but the response mediatype did not start with image/, so the bytes are not treated as an image. Unlike the HTML path, this uses plain http.Get (no SSRF-hardened client) and checks only the prefix.","triggerScenarios":"Calling the image fetch with a URL returning text/html (an error page), application/json, application/octet-stream, or video/* content types; hotlink-protected servers returning an HTML login page.","commonSituations":"Fetching user-supplied avatar/OG-image URLs that are actually HTML pages; CDNs serving the wrong content type; copy-pasting page URLs instead of direct image URLs into image fields.","solutions":["Use the direct image URL (ends in .png/.jpg or returns image/*), not the page URL","Verify with `curl -sI <url> | grep -i content-type`","If you own the server, serve the asset with a correct image/* Content-Type"],"exampleFix":"// before\nGetImage(\"https://example.com/photos/cat\") // HTML page\n// after\nGetImage(\"https://example.com/photos/cat.jpg\")","handlingStrategy":"validation","validationCode":"// Verify the URL returns an image before downloading fully (HEAD)\nfunc isImageURL(u string) bool {\n  resp, err := http.Head(u)\n  if err != nil { return false }\n  return strings.HasPrefix(resp.Header.Get(\"Content-Type\"), \"image/\")\n}","typeGuard":null,"tryCatchPattern":"// Fall back to a placeholder when the target is not an image\nimg, err := getter.GetImage(u)\nif err != nil && strings.Contains(err.Error(), \"wrong image mediatype\") {\n  img = placeholderImage(u)\n  err = nil\n}","preventionTips":["Validate image URLs with a HEAD request in the client","Store direct asset URLs, not page URLs, for image fields","Cap and verify content types at ingest in your own services"],"tags":["network","http","image","content-type"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}