golang/go · error

insecure URL: %s

Error message

insecure URL: %s

What it means

Thrown by cmd/go/internal/web.get when a URL with scheme 'http' is fetched in SecureOnly security mode. SecureOnly is the default mode for module fetching: it rejects plain HTTP to prevent credential and code injection over unencrypted links. The error is returned (not printed) so callers can wrap it with request context.

Source

Thrown at src/cmd/go/internal/web/http.go:223

			if cfg.BuildX {
				fmt.Fprintf(os.Stderr, "# get %s: %v\n", secure.Redacted(), err)
			}
			if security != Insecure || url.Scheme == "https" {
				// HTTPS failed, and we can't fall back to plain HTTP.
				// Report the error from the HTTPS attempt.
				return nil, err
			}
		}
	}

	if res == nil {
		switch url.Scheme {
		case "http":
			if security == SecureOnly {
				if cfg.BuildX {
					fmt.Fprintf(os.Stderr, "# get %s: insecure\n", url.Redacted())
				}
				return nil, fmt.Errorf("insecure URL: %s", url.Redacted())
			}
		case "":
			if security != Insecure {
				panic("should have returned after HTTPS failure")
			}
		default:
			if cfg.BuildX {
				fmt.Fprintf(os.Stderr, "# get %s: unsupported\n", url.Redacted())
			}
			return nil, fmt.Errorf("unsupported scheme: %s", url.Redacted())
		}

		insecure := new(urlpkg.URL)
		*insecure = *url
		insecure.Scheme = "http"
		if insecure.User != nil && security != Insecure {
			if cfg.BuildX {
				fmt.Fprintf(os.Stderr, "# get %s: insecure credentials\n", insecure.Redacted())

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Set GOINSECURE=<host>[,<host>...] env var so the host is fetched in Insecure mode (allows HTTP fallback and skips TLS verify).
  2. Switch the module/replace URL to https:// — the preferred fix.
  3. Route through an HTTPS-speaking GOPROXY (e.g. Athens, Athens-like proxy) that then talks HTTP upstream.
  4. For vanity imports, fix the go-import meta tag on the server to advertise https.

Example fix

// before: go.mod
replace example.com/m => http://internal.corp/m

// after (option A — HTTPS)
replace example.com/m => https://internal.corp/m

// after (option B — allow HTTP for that host)
// $ GOINSECURE=internal.corp go build
Defensive patterns

Strategy: validation

Validate before calling

// Validate URL scheme and security policy before fetching.
func isFetchAllowed(u *urlpkg.URL, allowInsecure map[string]bool) error {
    switch u.Scheme {
    case "https", "":
        return nil
    case "http":
        if !allowInsecure[u.Hostname()] {
            return fmt.Errorf("refusing plain-HTTP fetch for %s without GOINSECURE opt-in", u)
        }
        return nil
    default:
        return fmt.Errorf("unsupported scheme %q", u.Scheme)
    }
}

Prevention

When it happens

Trigger: Calling web.get/web.Get/web.GetBytes/web.GetMaybe with a URL whose Scheme=="http" while security==SecureOnly (the zero value). Happens when a go.mod has a plain-HTTP replace directive or a vanity import resolves to http:// without the host being listed in GOINSECURE.

Common situations: A private module server reachable only over HTTP inside a corp network; a git-over-HTTP vanity URL; CI environments where TLS termination is unavailable. The user forgot to set GOINSECURE=<host> or GOPROXY=https://...

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/97a6b0c42b99b438. Report an issue: GitHub.