Tencent/WeKnora · error
blocked by SSRF policy: %w
Error message
blocked by SSRF policy: %w
What it means
This error is returned when fetching a remote image is blocked because the target URL fails SSRF (server-side request forgery) validation. Whitelisted image hosts skip the check; all other URLs must pass secutils.ValidateURLForSSRF, which rejects private/loopback/link-local IPs and disallowed schemes. This is a deliberate security control, not an incidental failure.
Source
Thrown at internal/infrastructure/docparser/image_resolver.go:786
// fetchAndStoreRemoteImage applies the SSRF policy, downloads the image,
// rejects icons and uploads the bytes to storage.
//
// Both the Markdown and the HTML scan go through here so that the SSRF check,
// the icon filter and the whitelist behaviour cannot drift apart between the
// two syntaxes.
func fetchAndStoreRemoteImage(
ctx context.Context,
client *http.Client,
fileSvc interfaces.FileService,
tenantID uint64,
imgURL string,
) (*remoteImageResult, error) {
whitelisted := isWhitelistedImageHost(imgURL)
if !whitelisted {
if err := secutils.ValidateURLForSSRF(imgURL); err != nil {
return nil, fmt.Errorf("blocked by SSRF policy: %w", err)
}
}
data, mimeType, err := downloadImage(ctx, client, imgURL)
if err != nil {
return nil, fmt.Errorf("download: %w", err)
}
if isIconImage(data) {
return nil, errRemoteImageIsIcon
}
if whitelisted {
return &remoteImageResult{MimeType: mimeType, KeepOriginalURL: true}, nil
}
ext := extFromMime(mimeType)
if ext == "" {View on GitHub (pinned to 988cbb0330)
Solutions
- Check the URL: it must be a public http(s) address resolvable to a public IP
- Add the trusted host to the image-host whitelist if it is legitimately required
- Do not bypass the validator for user-supplied URLs (SSRF risk)
- Test the exact URL with secutils.ValidateURLForSSRF to see the specific rejection reason
Example fix
// before imgURL := "http://localhost:8080/logo.png" // blocked // after imgURL := "https://cdn.example.com/logo.png" // public URL passes SSRF validation
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(imgURL)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
return fmt.Errorf("reject non-http(s) url: %q", imgURL)
}
ips, err := net.LookupIP(u.Hostname())
if err != nil { return err }
for _, ip := range ips {
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() {
return fmt.Errorf("internal address not allowed: %v", ip)
}
} Try / catch
res, err := resolver.fetchAndStoreRemoteImage(ctx, imgURL, tenantID)
if err != nil {
if strings.Contains(err.Error(), "blocked by SSRF policy") {
return fmt.Errorf("image url %q rejected by security policy: %w", imgURL, err)
}
return err
} Prevention
- Only allow public http(s) image URLs from user content
- Maintain an explicit whitelist for trusted image hosts
- Never bypass SSRF validation for dynamic/user-supplied URLs
- Educate that blocks on 169.254.x / localhost are intentional security controls
When it happens
Trigger: fetchAndStoreRemoteImage called with an imgURL whose host is not whitelisted and which resolves to a private/loopback/metadata IP, uses a non-http(s) scheme, or is otherwise rejected by the SSRF validator.
Common situations: Documents containing images pointing at internal hosts (169.254.169.254, localhost, 10.x), file:// or other schemes, redirects to internal addresses, hosts not added to the whitelist.
Related errors
- URL rejected: %w
- base_url SSRF validation failed: %w
- URL rejected for security reasons: %v
- docreader address failed SSRF validation: %w
- zip URL blocked by SSRF check: %v
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/0ffb7e250b054e6a.
Report an issue: GitHub.