{"record":{"id":"eda736c4a4fab5de","repo":"larksuite/cli","slug":"invalid-url","errorCode":null,"errorMessage":"invalid URL","messagePattern":"invalid URL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/validate/url.go","lineNumber":84,"sourceCode":"\t}\n\tif ip.IsPrivate() {\n\t\treturn true\n\t}\n\tip16 := ip.To16()\n\tif ip16 == nil {\n\t\treturn true\n\t}\n\tif ip16[0]&0xfe == 0xfc { // fc00::/7 unique local address\n\t\treturn true\n\t}\n\treturn false\n}\n\n// ValidateDownloadSourceURL validates a download URL and blocks local/internal targets.\nfunc ValidateDownloadSourceURL(ctx context.Context, rawURL string) error {\n\tu, err := url.Parse(rawURL)\n\tif err != nil || u == nil {\n\t\treturn fmt.Errorf(\"invalid URL\")\n\t}\n\tif u.Scheme != \"http\" && u.Scheme != \"https\" {\n\t\treturn fmt.Errorf(\"only http/https URLs are supported\")\n\t}\n\t_, err = resolveDownloadHost(ctx, u.Hostname(), net.DefaultResolver.LookupIP)\n\treturn err\n}\n\ntype downloadLookupIPFunc func(context.Context, string, string) ([]net.IP, error)\n\nfunc resolveDownloadHost(ctx context.Context, rawHost string, lookupIP downloadLookupIPFunc) ([]net.IP, error) {\n\thost := strings.TrimSpace(strings.ToLower(rawHost))\n\tif host == \"\" {\n\t\treturn nil, fmt.Errorf(\"URL host is required\")\n\t}\n\tif host == \"localhost\" || strings.HasSuffix(host, \".localhost\") {\n\t\treturn nil, fmt.Errorf(\"local/internal host is not allowed\")\n\t}","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/validate/url.go#L66-L102","documentation":"ValidateDownloadSourceURL parses the caller-supplied download URL; if url.Parse fails or yields a nil URL, it throws \"invalid URL\". This is the entry-point validation before scheme checks and SSRF protection via resolveDownloadHost. It means the string is not a parseable absolute URL at all.","triggerScenarios":"downloadURLCommand, validateRemoteDocImageSource, or startURLDownload passes a string to ValidateDownloadSourceURL that url.Parse cannot parse — e.g. missing scheme with unparseable characters, unescaped control characters, or malformed percent-encoding.","commonSituations":"Typo or truncated URL, unquoted shell strings with control characters, input read from a file containing stray whitespace or multiple lines, or a URL list pasted as one value.","solutions":["Check the URL for typos and ensure it is complete and on one line.","Confirm the string is a single URL, not a list or a path; trim whitespace.","Percent-encode special characters in the URL (spaces, control chars).","Validate locally first: `python3 -c \"import urllib.parse,sys; urllib.parse.urlparse(sys.argv[1])\" \"$URL\"`."],"exampleFix":"// before\nlark-cli download url \"$URL\"   # URL read from file, contains a newline\n// after\nURL=$(head -n1 urls.txt | tr -d '[:space:]')\nlark-cli download url \"$URL\"","handlingStrategy":"validation","validationCode":"u, err := url.Parse(rawURL)\nif err != nil || u == nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"not a valid absolute URL: %q\", rawURL)\n}","typeGuard":null,"tryCatchPattern":"if err := validate.ValidateDownloadSourceURL(ctx, raw); err != nil {\n    if strings.Contains(err.Error(), \"invalid URL\") {\n        return fmt.Errorf(\"check the URL string (complete, single line, percent-encoded): %w\", err)\n    }\n    return err\n}","preventionTips":["Ensure URLs are complete, on one line, and properly percent-encoded.","Trim whitespace/newlines from URLs read from files or command output.","Sanity-check URLs with a local parser before invoking the CLI.","Use https:// explicitly rather than relying on defaults."],"tags":["input-validation","url","download"],"backgroundTag":"invalid-url","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"}