larksuite/cli · error

blocked redirect target: %w

Error message

blocked redirect target: %w

What it means

On every redirect, CheckRedirect re-runs ValidateDownloadSourceURL on the redirect target (internal/validate/url.go:156). That validator rejects malformed URLs, non-http/https schemes, and hosts that resolve to localhost or private/restricted IP ranges (SSRF protection). When it fails, the redirect is wrapped as 'blocked redirect target' and the request aborts — the library refuses to be redirected into an internal network.

Source

Thrown at internal/validate/url.go:156

	cloned.Transport = &downloadSchemeTransport{
		base:      cloneDownloadTransport(base.Transport),
		allowHTTP: opts.AllowHTTP,
	}
	cloned.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		if len(via) >= opts.MaxRedirects {
			return fmt.Errorf("too many redirects")
		}
		if len(via) > 0 {
			prev := via[len(via)-1]
			if strings.EqualFold(prev.URL.Scheme, "https") && strings.EqualFold(req.URL.Scheme, "http") {
				return fmt.Errorf("redirect from https to http is not allowed")
			}
		}
		if !opts.AllowHTTP && !strings.EqualFold(req.URL.Scheme, "https") {
			return fmt.Errorf("only https URLs are supported")
		}
		if err := ValidateDownloadSourceURL(req.Context(), req.URL.String()); err != nil {
			return fmt.Errorf("blocked redirect target: %w", err)
		}
		return nil
	}

	return &cloned
}

type downloadSchemeTransport struct {
	base      http.RoundTripper
	allowHTTP bool
}

func (t *downloadSchemeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	if req == nil || req.URL == nil {
		return nil, errs.NewInternalError(
			errs.SubtypeUnknown,
			"download transport received a nil request",
		)

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Inspect the redirect target (final URL in the error context) and use a URL on a public host that does not redirect into private ranges.
  2. Verify DNS resolution of the redirect host from the runtime environment; fix resolver/connectivity issues if 'failed to resolve host' is the cause.
  3. Do not attempt to bypass: the private/localhost blocklist is deliberate SSRF protection; move the asset to a public HTTPS location instead.

Example fix

// before: endpoint redirects to internal host
resp, err := client.Get("https://files.example.com/dl") // 302 -> http://10.0.0.5/asset
// after: serve a direct public URL
resp, err := client.Get("https://cdn.example.com/asset")
Defensive patterns

Strategy: validation

Validate before calling

// Pre-screen the URL with the library's own validator before downloading.
if err := validate.ValidateDownloadSourceURL(ctx, src); err != nil {
    return fmt.Errorf("download source rejected upfront: %w", err)
}

Try / catch

resp, err := client.Get(url)
if err != nil {
    var blocked bool
    if strings.Contains(err.Error(), "blocked redirect target") {
        blocked = true
    }
    if blocked {
        return fmt.Errorf("source redirects into a restricted network; refusing: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: A redirect whose Location points to localhost, 127.0.0.1, RFC1918/private ranges, link-local/CGNAT/multicast addresses, an unresolvable hostname ('failed to resolve host'), or a non-http/https scheme — while following redirects on a NewDownloadHTTPClient client.

Common situations: A compromised or misbehaving source redirecting into cloud metadata endpoints (169.254.169.254); internal staging hosts that 302 to intranet URLs; DNS failures in constrained environments; redirect to an unusual scheme like file://.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/0da1198ff3ec48cc. Report an issue: GitHub.