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

  1. Only pass page URLs verbatim from previous Cloud Healthcare API responses (they use healthcare.googleapis.com)
  2. Never let untrusted text supply the page URL host — validate the host prefix yourself before invoking
  3. If you front the API with your own proxy, fetch pages through the proxy's own pagination rather than rewriting the host
  4. 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

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


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/a7e134e040ff94bd. Report an issue: GitHub.