googleapis/mcp-toolbox · error
URL host must be an allowed FHIR host, got %q
Error message
URL host must be an allowed FHIR host, got %q
What it means
validateFHIRPageURL lowercases the host (stripping any port) and checks it against the allowedFHIRHosts allowlist (healthcare.googleapis.com and healthcare.mtls.googleapis.com). This error means the pagination URL points at a host that is not a genuine Google Healthcare API endpoint — a defense against SSRF where a malicious or buggy page link could make the server fetch arbitrary internal URLs.
Source
Thrown at internal/sources/cloudhealthcare/cloud_healthcare.go:340
}
func (s *Source) validateFHIRPageURL(pageURL string) (string, error) {
parsed, err := url.Parse(pageURL)
if err != nil {
return "", fmt.Errorf("invalid page URL: %w", err)
}
if parsed.Scheme != "https" {
return "", fmt.Errorf("URL scheme must be https, got %q", parsed.Scheme)
}
parsed.Host = strings.ToLower(parsed.Host)
host := parsed.Host
if h, _, err := net.SplitHostPort(host); err == nil {
host = h
}
if _, ok := allowedFHIRHosts[host]; !ok {
return "", fmt.Errorf("URL host must be an allowed FHIR host, got %q", host)
}
// Clean and split path
cleanPath := path.Clean(parsed.Path)
// Truncate leading and trailing slashes for easier splitting
trimmed := strings.Trim(cleanPath, "/")
parts := strings.Split(trimmed, "/")
// Page URL format Reference: https://docs.cloud.google.com/healthcare-api/docs/how-tos/fhir-search#using_the_search_method_with_get
if len(parts) < 10 {
return "", fmt.Errorf("invalid FHIR URL path structure: path too short")
}
if !isValidAPIVersion(parts[0]) {
return "", fmt.Errorf("invalid API version prefix: %q", parts[0])
}
if parts[1] != "projects" {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Only pass page URLs verbatim from previous Cloud Healthcare API responses (they use healthcare.googleapis.com)
- Never let untrusted text supply the page URL host — validate the host prefix yourself before invoking
- If you front the API with your own proxy, fetch pages through the proxy's own pagination rather than rewriting the host
- Contact the library maintainers to extend allowedFHIRHosts if a legitimate Google host is missing
Example fix
// before (host substituted) next := "https://internal-proxy.corp/v1/projects/.../fhir/Patient?pageToken=x" // after (host from the original Google response) next := "https://healthcare.googleapis.com/v1/projects/.../fhir/Patient?pageToken=x"
Defensive patterns
Strategy: validation
Validate before calling
function isAllowedFHIRHost(u) { const h = new URL(u).hostname.toLowerCase().replace(/:\d+$/, ''); return ['healthcare.googleapis.com','healthcare.mtls.googleapis.com'].includes(h); } Prevention
- Only feed page URLs taken directly from Cloud Healthcare API responses back into pagination
- Sanitize any LLM-provided URL: parse it and reject if the host is not healthcare.googleapis.com
- Never follow pagination links embedded in untrusted document text — they may point at internal hosts
When it happens
Trigger: A page URL with a substituted host (e.g. evil.example.com, an internal 10.x hostname, or metadata.google.internal) is passed to FHIRFetchPage; regional endpoints or a custom service endpoint host were pasted into the page URL.
Common situations: Prompt-injection or poisoned API responses tricking an agent into fetching an attacker URL; developers pointing page URLs at a self-hosted FHIR proxy; mixing up the FHIR store's selfLink host with the API host.
Related errors
- URL scheme must be https, got %q
- path must be relative and cannot override base host
- local path %q is not under any allowed local roots for sourc
- redirect to blocked IP %s denied
- redirect host %s resolves to blocked IP %s
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/a7e134e040ff94bd.
Report an issue: GitHub.