siyuan-note/siyuan · error
generated image URL must use HTTPS
Error message
generated image URL must use HTTPS
What it means
downloadGeneratedImage parses the URL returned by the image model and requires scheme https with a non-empty host. This is an SSRF/security guard: plain-http or malformed URLs returned by a compromised or misbehaving provider are rejected before any request is made. Non-https URLs would also leak generated content in cleartext.
Solutions
- Configure the provider/proxy to return absolute https:// URLs
- If you control the image host, serve it over HTTPS
- URL-encode/fix the URL at the provider side; verify with url.Parse what is malformed
- As an operator-only workaround behind a trusted private network, host-rewrite the URL to https before passing it downstream (not recommended)
Example fix
// before rawURL := "http://cdn.example.com/img.png" // rejected: not https // after rawURL := "https://cdn.example.com/img.png" // pass data, err := downloadGeneratedImage(ctx, rawURL)
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(rawURL)
if err != nil || u.Scheme != "https" || u.Host == "" {
return errors.New("image URL must be absolute https")
} Prevention
- Only integrate image providers that return absolute https URLs
- Validate URLs at the boundary before handing them to the downloader
- Reject scheme-relative or relative URLs early
When it happens
Trigger: result.URL from the provider starts with http:// (not https), is scheme-relative like //host/img, or fails url.Parse entirely (spaces, control chars, relative path).
Common situations: Self-hosted/proxied image service returning http:// LAN URLs; provider returning a relative path instead of an absolute URL; corrupted URL containing unencoded characters; man-in-the-middle or malicious provider response.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- generated image redirect is not allowed
- access to private/internal IP is prohibited
- access to private/internal IP is prohibited
- data?.msg || data?.message ||…
- failed to resolve host:
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/89206ce5d22e9f48.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/openai.go:930
} else if result.URL != "" {
data, err = downloadGeneratedImage(requestCtx, result.URL)
} else {
err = errors.New("image model returned neither base64 data nor URL")
}
if err != nil {
return GeneratedImage{}, err
}
mimeType, extension, err := ValidateGeneratedImage(data)
if err != nil {
return GeneratedImage{}, err
}
return GeneratedImage{Data: data, MIMEType: mimeType, Extension: extension, RevisedPrompt: result.RevisedPrompt}, nil
}
func downloadGeneratedImage(ctx context.Context, rawURL string) ([]byte, error) {
parsed, err := url.Parse(rawURL)
if err != nil || parsed.Scheme != "https" || parsed.Host == "" {
return nil, errors.New("generated image URL must use HTTPS")
}
if err = CheckHostSSRF(parsed.Hostname()); err != nil {
return nil, err
}
client := generatedImageHTTPClient()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil)
if err != nil {
return nil, err
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("download generated image failed with status %d", resp.StatusCode)
}
if resp.ContentLength > maxGeneratedImageBytes {View on GitHub (pinned to 9f775e8a12)