{"record":{"id":"182c79c5dbb8460f","repo":"larksuite/cli","slug":"invalid-s-q-missing-host","errorCode":null,"errorMessage":"invalid %s %q: missing host","messagePattern":"invalid (.+?) %q: missing host","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/transport/config.go","lineNumber":204,"sourceCode":"// proxyURL validates the fixed configured proxy configuration and returns its URL.\nfunc (c *Config) proxyURL() (*url.URL, error) {\n\traw := strings.TrimSpace(c.Proxy)\n\tif raw == \"\" {\n\t\treturn nil, fmt.Errorf(\"%s is empty\", envvars.CliProxyAddress)\n\t}\n\tredacted := redactProxyURL(raw)\n\tu, err := url.Parse(raw)\n\tif err != nil {\n\t\t// Do not wrap the raw url.Parse error: its string embeds the original\n\t\t// URL, which can contain userinfo (user:password). Return a redacted,\n\t\t// generic message instead.\n\t\treturn nil, fmt.Errorf(\"invalid %s %q: malformed URL\", envvars.CliProxyAddress, redacted)\n\t}\n\tif u.Scheme != \"http\" {\n\t\treturn nil, fmt.Errorf(\"invalid %s %q: scheme must be http\", envvars.CliProxyAddress, redacted)\n\t}\n\tif u.Host == \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid %s %q: missing host\", envvars.CliProxyAddress, redacted)\n\t}\n\t// Security hardening: only allow a loopback proxy. This prevents accidental\n\t// cross-machine proxying of credentials/traffic.\n\tif u.Hostname() != \"127.0.0.1\" {\n\t\treturn nil, fmt.Errorf(\"invalid %s %q: host must be 127.0.0.1\", envvars.CliProxyAddress, redacted)\n\t}\n\tif u.Port() == \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid %s %q: explicit port is required\", envvars.CliProxyAddress, redacted)\n\t}\n\tif u.Path != \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid %s %q: path is not allowed\", envvars.CliProxyAddress, redacted)\n\t}\n\tif u.RawQuery != \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid %s %q: query is not allowed\", envvars.CliProxyAddress, redacted)\n\t}\n\tif u.Fragment != \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid %s %q: fragment is not allowed\", envvars.CliProxyAddress, redacted)\n\t}","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/transport/config.go#L186-L222","documentation":"Security hardening: the proxy plugin only allows a loopback proxy on 127.0.0.1, preventing accidental cross-machine proxying of CLI credentials and traffic. Any other hostname or IP — including localhost, ::1, 0.0.0.0, or a LAN IP — is rejected with a redacted address in the message.","triggerScenarios":"LARKSUITE_CLI_PROXY_ADDRESS set to `http://localhost:8080`, `http://[::1]:8080`, `http://192.168.1.10:8080`, or a DNS name, while proxy mode is enabled; ApplyToTransport fails during startup.","commonSituations":"Assuming 'localhost' is accepted; pointing at a proxy running in a container/VM by its IP; copying a corporate proxy address that isn't loopback.","solutions":["Use the literal loopback IP with an explicit port: `export LARKSUITE_CLI_PROXY_ADDRESS=http://127.0.0.1:8080` (localhost is NOT accepted).","If your proxy runs elsewhere, run a local forwarder on 127.0.0.1 that relays to it, and point the variable at the local port.","Check the hostname portion exactly matches 127.0.0.1 — no brackets, no name: `echo $LARKSUITE_CLI_PROXY_ADDRESS`.","Update proxy_config.json's LARKSUITE_CLI_PROXY_ADDRESS the same way if configured via file."],"exampleFix":"// before\nexport LARKSUITE_CLI_PROXY_ADDRESS=http://localhost:8080\n// after\nexport LARKSUITE_CLI_PROXY_ADDRESS=http://127.0.0.1:8080","handlingStrategy":"validation","validationCode":"host=\"${LARKSUITE_CLI_PROXY_ADDRESS#http://}\"; host=\"${host%%:*}\"\nif [ \"$host\" != \"127.0.0.1\" ]; then echo \"proxy host must be 127.0.0.1, got: $host\" >&2; fi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use the literal IP 127.0.0.1 — 'localhost' and '::1' are rejected.","For a remote/container proxy, run a local relay bound to 127.0.0.1 and point the variable at it.","This restriction is intentional credential-safety hardening; don't work around it by proxying other machines' traffic.","Keep the address in one place (env var or proxy_config.json) to avoid drift."],"tags":["proxy","security","loopback","config"],"backgroundTag":"proxy-host-not-allowed","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}