Tencent/WeKnora · error

URL has no hostname

Error message

URL has no hostname

What it means

ValidateURLForSSRF requires the parsed URL to carry a hostname. A URL like 'https:///path', 'file://', or a scheme-only string yields an empty parsed.Hostname() and is rejected with 'URL has no hostname'. Without a host the SSRF checks (IP-literal filtering, whitelist lookup) have nothing to evaluate, so the URL cannot be deemed safe.

Source

Thrown at internal/utils/security.go:1198

func ValidateURLForSSRF(rawURL string) error {
	if rawURL == "" {
		return nil // callers that require non-empty should validate separately
	}

	// Normalise: if no scheme, prepend https:// so url.Parse works correctly.
	normalized := rawURL
	if !strings.Contains(normalized, "://") {
		normalized = "https://" + normalized
	}

	parsed, err := url.Parse(normalized)
	if err != nil {
		return fmt.Errorf("invalid URL: %w", err)
	}

	hostname := parsed.Hostname()
	if hostname == "" {
		return fmt.Errorf("URL has no hostname")
	}

	// A whitelist relaxes host/IP restrictions only. It must never turn other
	// schemes (file://, gopher://, etc.) into valid outbound request targets.
	scheme := strings.ToLower(parsed.Scheme)
	if scheme != "http" && scheme != "https" {
		return fmt.Errorf("invalid scheme: %s (only http/https allowed)", scheme)
	}

	// If the host is whitelisted, skip the heavy checks.
	if IsSSRFWhitelisted(hostname) {
		return nil
	}

	// Delegate to the full SSRF validation (uses the normalised URL).
	if safe, reason := isSSRFSafeURL(normalized); !safe {
		return fmt.Errorf("SSRF validation failed: %s", reason)
	}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Provide the full host in the endpoint: 'https://minio.example.com:9000' instead of 'https://:9000'
  2. Check that config substitution produced a non-empty hostname (echo the resolved value before deployment)
  3. Restore the missing double slash for scheme URLs ('https://host' not 'https:/host')
  4. Add a pre-flight url.Parse + Hostname() check in the caller to fail with a clearer config error

Example fix

// before
endpoint := "https://${OSS_HOST}" // OSS_HOST unset → https://
// after
host := os.Getenv("OSS_HOST")
if host == "" {
    return fmt.Errorf("OSS_HOST must be set")
}
endpoint := "https://" + host
Defensive patterns

Strategy: validation

Validate before calling

n := endpoint
if !strings.Contains(n, "://") { n = "https://" + n }
u, err := url.Parse(n)
if err != nil || u.Hostname() == "" {
    return fmt.Errorf("endpoint %q has no hostname", endpoint)
}

Type guard

func hasHostname(raw string) bool {
    if !strings.Contains(raw, "://") { raw = "https://" + raw }
    u, err := url.Parse(raw)
    return err == nil && u.Hostname() != ""
}

Prevention

When it happens

Trigger: Calling any storage client constructor or CheckObsConnectivity with a URL missing its host portion — e.g. 'https:///bucket', 'http://:9000', or an endpoint value that after normalization is just a scheme, or was mistyped as 'https:/myhost' (single slash collapses).

Common situations: Config where only the port was given, template variables expanding to empty hostnames ('https://${MISSING}/'), typo'd URLs with a single slash after the scheme, or copying 'https://' from a browser address bar with the domain trimmed.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/21ded480298097bc. Report an issue: GitHub.