Tencent/WeKnora · error
zip URL blocked by SSRF check: %v
Error message
zip URL blocked by SSRF check: %v
What it means
The full_zip_url returned by MinerU Cloud was rejected by utils.ValidateURLForSSRF before download in downloadAndExtractZip (mineru_cloud_converter.go:357). The library blocks URLs that resolve to private/loopback/link-local addresses or disallowed schemes to prevent server-side request forgery. If the URL is a legitimate public storage link, this indicates an over-restrictive SSRF policy or a DNS/environment quirk (e.g. internal DNS resolving the storage host to a private IP).
Source
Thrown at internal/infrastructure/docparser/mineru_cloud_converter.go:357
return "", nil, fmt.Errorf("MinerU Cloud state=done but no markdown/content or full_zip_url")
}
md, imageRefs, err := downloadAndExtractZip(item.FullZipURL)
if err != nil {
return "", nil, fmt.Errorf("extract zip: %w", err)
}
logger.Infof(context.Background(), "[MinerUCloud] parsed (zip), markdown=%d chars, images=%d", len(md), len(imageRefs))
return md, imageRefs, nil
}
// --- ZIP handling ---
var imgRefPattern = regexp.MustCompile(`!\[[^\]]*\]\(([^)]+)\)`)
func downloadAndExtractZip(zipURL string) (string, []types.ImageRef, error) {
if err := utils.ValidateURLForSSRF(zipURL); err != nil {
return "", nil, fmt.Errorf("zip URL blocked by SSRF check: %v", err)
}
client := utils.NewSSRFSafeHTTPClient(utils.SSRFSafeHTTPClientConfig{Timeout: 120 * time.Second, MaxRedirects: 5})
resp, err := client.Get(zipURL)
if err != nil {
return "", nil, fmt.Errorf("download zip: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", nil, fmt.Errorf("download zip status %d", resp.StatusCode)
}
zipData, err := io.ReadAll(resp.Body)
if err != nil {
return "", nil, fmt.Errorf("read zip body: %w", err)
}
zr, err := zip.NewReader(bytes.NewReader(zipData), int64(len(zipData)))
if err != nil {View on GitHub (pinned to 988cbb0330)
Solutions
- Inspect the wrapped %v cause to see which SSRF rule fired (scheme, private IP, port).
- If the storage host is legitimately internal, add it to the SSRF allowlist or configure the allowed CIDR ranges in the SSRF client config.
- Ensure MinerU Cloud returns publicly resolvable full_zip_url values (check the deployment's public endpoint configuration).
- Never bypass SSRF checks for untrusted URLs; only allowlist verified internal storage hosts.
Example fix
// before — blanket bypass (unsafe)
// md, imageRefs, err := download zip without check
// after — allowlist the trusted internal storage CIDR
utils.NewSSRFSafeHTTPClient(utils.SSRFSafeHTTPClientConfig{
Timeout: 120 * time.Second,
MaxRedirects: 5,
AllowedCIDRs: []string{"10.0.0.0/8"}, // only if storage is trusted-internal
}) Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(zipURL)
if err != nil {
return err
}
if u.Scheme != "https" && u.Scheme != "http" {
return fmt.Errorf("unsupported scheme: %s", u.Scheme)
}
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("zip URL resolves to non-public address: %v", ip)
}
} Type guard
func isPublicHTTPURL(raw string) bool {
u, err := url.Parse(raw)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
return false
}
ips, err := net.LookupIP(u.Hostname())
if err != nil {
return false
}
for _, ip := range ips {
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() {
return false
}
}
return true
} Try / catch
md, images, err := pollBatchResult(ctx, batchID)
if err != nil {
if strings.Contains(err.Error(), "zip URL blocked by SSRF check") {
// expected for internal URLs: use an allowlisted fetcher or fail fast
return fmt.Errorf("result URL not fetchable from this network: %w", err)
}
return err
} Prevention
- Pre-validate zip URLs for scheme and public resolvability before conversion flows that require zip download.
- If result storage is internal, configure the SSRF allowlist explicitly — never disable the check.
- Ensure the MinerU deployment exposes publicly resolvable full_zip_url values.
When it happens
Trigger: extractDoneResult -> downloadAndExtractZip receives a zipURL that fails SSRF validation: non-http(s) scheme, localhost/loopback host, private or link-local IP resolution, metadata endpoints (169.254.169.254), or disallowed ports.
Common situations: Self-hosted/proxied MinerU deployments whose result URLs point at internal storage; test environments using local mock URLs; containers where the storage host resolves to a cluster-internal IP; misconfigured public base URL falling back to an internal address.
Related errors
- URL rejected: %w
- base_url SSRF validation failed: %w
- URL rejected for security reasons: %v
- docreader address failed SSRF validation: %w
- blocked by SSRF policy: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/c65b068dd8b2a76b.
Report an issue: GitHub.