amir20/dozzle · error

refusing auth realm : must be https

Error message

refusing auth realm %q: must be https

What it means

validateRealm refuses to fetch a registry token from a realm that is not HTTPS. The only exception is plain HTTP on loopback registries explicitly marked insecure and pointing at the same host as the registry itself. This prevents a registry (or a MITM) from redirecting token requests to an insecure third-party host.

Solutions

  1. Serve the token endpoint over HTTPS; plain HTTP realms are rejected by design.
  2. For a local dev registry, mark it insecure so loopback HTTP to the same host is allowed.
  3. If the realm host is intentionally different, it must still use HTTPS.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at internal/imagecheck/registry.go:246 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/9e87a8663d5485f3. Report an issue: GitHub.

Appendix: source

Thrown at internal/imagecheck/registry.go:246

}

// validateRealm restricts where a registry can send us for a token.
func validateRealm(endpoint *url.URL, ref Reference) error {
	if endpoint.Host == "" {
		return fmt.Errorf("auth realm %q has no host", endpoint)
	}

	if endpoint.Scheme == "https" {
		return nil
	}

	// A loopback registry is already trusted over plain HTTP, but only for
	// itself: it cannot send us to some other host in the clear.
	if endpoint.Scheme == "http" && ref.Insecure() && sameHost(endpoint.Host, ref.Registry) {
		return nil
	}

	return fmt.Errorf("refusing auth realm %q: must be https", endpoint)
}

func sameHost(a, b string) bool {
	return strings.EqualFold(a, b)
}

// parseChallenge pulls realm and service out of a Bearer WWW-Authenticate
// header, e.g. `Bearer realm="https://auth.docker.io/token",service="registry.docker.io"`.
func parseChallenge(header string) (realm string, service string) {
	if !strings.HasPrefix(strings.ToLower(header), "bearer ") {
		return "", ""
	}

	for part := range strings.SplitSeq(header[len("bearer "):], ",") {
		key, value, found := strings.Cut(strings.TrimSpace(part), "=")
		if !found {
			continue
		}

View on GitHub (pinned to d9463cbe21)