Tencent/WeKnora · error
docreader address failed SSRF validation: %w
Error message
docreader address failed SSRF validation: %w
What it means
NewHTTPDocumentReader validates the supplied docreader base URL with secutils.ValidateURLForSSRF before storing it and returns this wrapped error when the URL is not SSRF-safe (e.g. private/loopback/link-local addresses, disallowed scheme, or otherwise forbidden target). This guards against server-side request forgery where an attacker-controlled docreader address would make the service fetch from internal infrastructure.
Source
Thrown at internal/infrastructure/docparser/http_parser.go:69
MarkdownContent string `json:"markdown_content"`
ImageRefs []httpImageRef `json:"image_refs,omitempty"`
ImageDirPath string `json:"image_dir_path,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
Error string `json:"error,omitempty"`
}
// HTTPDocumentReader implements DocumentReader over HTTP/JSON.
type HTTPDocumentReader struct {
mu sync.RWMutex
baseURL string
client *http.Client
}
func NewHTTPDocumentReader(baseURL string) (*HTTPDocumentReader, error) {
baseURL = strings.TrimSuffix(strings.TrimSpace(baseURL), "/")
if baseURL != "" {
if err := secutils.ValidateURLForSSRF(baseURL); err != nil {
return nil, fmt.Errorf("docreader address failed SSRF validation: %w", err)
}
}
clientCfg := secutils.DefaultSSRFSafeHTTPClientConfig()
clientCfg.Timeout = 5 * time.Minute
p := &HTTPDocumentReader{
baseURL: baseURL,
client: secutils.NewSSRFSafeHTTPClient(clientCfg),
}
if p.baseURL != "" {
logger.Infof(context.Background(), "INFO: HTTP docreader base URL: %s", p.baseURL)
}
return p, nil
}
func (p *HTTPDocumentReader) base() string {
p.mu.RLock()
defer p.mu.RUnlock()
return p.baseURLView on GitHub (pinned to 988cbb0330)
Solutions
- Point the docreader address at a public/allowed URL that passes ValidateURLForSSRF (proper public host, https scheme)
- Read the wrapped validation error to see exactly which rule failed (scheme, private IP, loopback, etc.) and adjust the URL accordingly
- If the docreader legitimately runs internally, deploy it behind an approved public gateway/proxy endpoint rather than passing the internal address directly
- Fix malformed URLs: ensure a single scheme (http:// or https://), no whitespace, no trailing garbage before validation
- If this is a trusted local dev setup, use the configuration mechanism intended for dev mode instead of bypassing validation
Example fix
// before
reader, err := docparser.NewHTTPDocumentReader("http://127.0.0.1:8000")
// error: docreader address failed SSRF validation: loopback address forbidden
// after
reader, err := docparser.NewHTTPDocumentReader("https://docreader.example.com") Defensive patterns
Strategy: validation
Validate before calling
url := strings.TrimSuffix(strings.TrimSpace(cfg.DocreaderBaseURL), "/")
if url != "" {
if err := secutils.ValidateURLForSSRF(url); err != nil {
return nil, fmt.Errorf("configured docreader url rejected: %w", err)
}
}
reader, err := docparser.NewHTTPDocumentReader(url) Try / catch
reader, err := docparser.NewHTTPDocumentReader(cfg.DocreaderBaseURL)
if err != nil {
var ssrfErr error
if strings.Contains(err.Error(), "failed SSRF validation") {
return nil, fmt.Errorf("config error: docreader url %q is not SSRF-safe: %w", cfg.DocreaderBaseURL, err)
}
_ = ssrfErr
return nil, err
} Prevention
- Never configure localhost, 127.0.0.1, or private/metadata IPs as the docreader address in shared environments
- Expose internal docreader instances through an approved public gateway/ingress
- Validate any user- or discovery-supplied docreader URL at config-load time, before constructing the reader
- Use https URLs with explicit hosts; avoid scheme typos and stray whitespace
When it happens
Trigger: Constructing HTTPDocumentReader via NewHTTPDocumentReader (from initDocReaderClient or ResolveDocumentReader) with a baseURL that points at localhost/127.0.0.1, a private RFC1918 address, a metadata endpoint like 169.254.169.254, a non-http(s) scheme, or a malformed URL that fails validation.
Common situations: Local development pointing the docreader at http://localhost:8000 which SSRF policy rejects in production-mode builds; operator configures an internal cluster IP or k8s service name that the validator classifies as private; config/env value contains a typo or extra scheme making validation fail; dynamic address resolution (ResolveDocumentReader) yields a private IP for a hostname.
Related errors
- URL rejected: %w
- base_url SSRF validation failed: %w
- URL rejected for security reasons: %v
- blocked by SSRF policy: %w
- zip URL blocked by SSRF check: %v
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/d311779d639dfa3b.
Report an issue: GitHub.