larksuite/cli · error

invalid proxy address %q: userinfo is not allowed

Error message

invalid proxy address %q: userinfo is not allowed

What it means

ValidateProxyAddr rejects any userinfo (user:pass@) in the proxy URL unconditionally, because the sidecar protocol authenticates with HMAC headers, not HTTP basic auth; the userinfo slot only enables phishing like http://127.0.0.1@attacker.com where the visible host is not the real host.

Source

Thrown at sidecar/protocol.go:163

		host, port, err := net.SplitHostPort(addr)
		if err != nil {
			return fmt.Errorf("invalid proxy address %q: expected host:port or http://host:port", addr)
		}
		if host == "" || port == "" {
			return fmt.Errorf("invalid proxy address %q: host and port must not be empty", addr)
		}
		if !isSameHost(host) {
			return errNotSameHost(addr)
		}
		return nil
	}

	u, err := url.Parse(addr)
	if err != nil {
		return fmt.Errorf("invalid proxy address %q: %w", addr, err)
	}
	if u.User != nil {
		return fmt.Errorf("invalid proxy address %q: userinfo is not allowed", addr)
	}
	if u.Scheme == "https" {
		return fmt.Errorf("invalid proxy address %q: use http:// — sidecar is "+
			"same-host only (loopback or virtual same-host bridge), so TLS adds "+
			"no security; cross-machine deployment is out of scope", addr)
	}
	if u.Scheme != "http" {
		return fmt.Errorf("invalid proxy address %q: scheme must be http", addr)
	}
	if u.Host == "" {
		return fmt.Errorf("invalid proxy address %q: missing host", addr)
	}
	if u.Path != "" && u.Path != "/" {
		return fmt.Errorf("invalid proxy address %q: path is not allowed", addr)
	}
	// u.Hostname() strips the port and unwraps IPv6 brackets.
	if !isSameHost(u.Hostname()) {
		return errNotSameHost(addr)

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Remove the user:pass@ portion and keep only `http://host:port`, e.g. `export LARKSUITE_CLI_AUTH_PROXY="http://127.0.0.1:16384"`.
  2. Do not use basic-auth proxy URLs here — the sidecar authenticates via HMAC headers (X-Lark-Proxy-Signature), so credentials in the URL are unnecessary and unsupported.
  3. Double-check the host after the '@' is the one you intend; if you pasted a URL with '@', the real host may not be loopback.
  4. Run the sidecar locally and use its plain loopback address.

Example fix

// before
export LARKSUITE_CLI_AUTH_PROXY="http://user:secret@127.0.0.1:16384"
// after
export LARKSUITE_CLI_AUTH_PROXY="http://127.0.0.1:16384"
Defensive patterns

Strategy: validation

Validate before calling

u, _ := url.Parse(addr)
if u != nil && u.User != nil {
	return errors.New("proxy URL must not contain user:pass@; sidecar uses HMAC headers, not basic auth")
}

Type guard

func hasNoUserinfo(addr string) bool {
	u, err := url.Parse(addr)
	return err == nil && u.User == nil
}

Try / catch

if err := sidecar.ValidateProxyAddr(addr); err != nil {
	if strings.Contains(err.Error(), "userinfo is not allowed") {
		return fmt.Errorf("strip user:pass@ from LARKSUITE_CLI_AUTH_PROXY; auth is via HMAC headers: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: ValidateProxyAddr is called (via ResolveAccount / ResolveInterceptor / init) with a value containing '@' userinfo, e.g. "http://user:pass@127.0.0.1:16384" or "http://127.0.0.1@attacker.com:16384" — often from pasting a generic proxy URL that includes credentials.

Common situations: Reusing a corporate HTTP proxy URL (which commonly embeds basic-auth credentials) as the sidecar address; migrating config from a standard proxy tool; a phishing/decoy URL that hides the real host behind a plausible userinfo.

Related errors


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