{"record":{"id":"89df555535860b78","repo":"valyala/fasthttp","slug":"invalid-host-q","errorCode":null,"errorMessage":"invalid host %q","messagePattern":"invalid host %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"uri.go","lineNumber":468,"sourceCode":"\t\tzone := bytes.Index(host[:i], []byte(\"%25\"))\n\t\tif zone >= 0 {\n\t\t\thost1, err := unescape(host[:zone], encodeHost)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\thost2, err := unescape(host[zone:i], encodeZone)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\thost3, err := unescape(host[i:], encodeHost)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\treturn append(host1, append(host2, host3...)...), nil\n\t\t}\n\t} else {\n\t\tif bytes.IndexByte(host, '[') >= 0 || bytes.IndexByte(host, ']') >= 0 {\n\t\t\treturn nil, fmt.Errorf(\"invalid host %q\", host)\n\t\t}\n\n\t\tif i := bytes.LastIndexByte(host, ':'); i != -1 {\n\t\t\tif bytes.IndexByte(host[:i], ':') != -1 {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid host %q with multiple port delimiters\", host)\n\t\t\t}\n\n\t\t\tcolonPort := host[i:]\n\t\t\tif !validOptionalPort(colonPort) {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid port %q after host\", colonPort)\n\t\t\t}\n\t\t}\n\t}\n\n\tvar err error\n\tif host, err = unescape(host, encodeHost); err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":450,"sourceCodeEnd":486,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/uri.go#L450-L486","documentation":"For non-bracketed hosts, parseHost rejects any host containing '[' or ']' with \"invalid host %q\", since brackets are only legal around IPv6 literals. It also rejects multiple ':' port delimiters with a related error. This keeps regfile-style hosts strict and unambiguous.","triggerScenarios":"URI.Parse with hosts like \"http://ex[ample.com/\", \"http://host]x/\", or a stray unmatched bracket anywhere in a non-IPv6 host.","commonSituations":"Client-supplied Host headers/targets with stray brackets; template or concatenation bugs when building URLs; malformed proxy-form targets forwarded by upstream proxies.","solutions":["Strip or percent-encode stray brackets before parsing","Validate the host with net/url.Parse or a host regex prior to fasthttp Parse","Reject the request with 400 when brackets are not part of a valid IPv6 literal","Fix URL-construction code that inserts unescaped values into host position"],"exampleFix":"// before\nvar u uri.URI\nu.Parse(nil, nil, []byte(\"http://ex[ample.com/\")) // stray '['\n// after\nraw := strings.ReplaceAll(\"http://ex[ample.com/\", \"[\", \"%5B\") // encode or fix host\nvar u uri.URI\nerr := u.Parse(nil, nil, []byte(raw))","handlingStrategy":"validation","validationCode":"func hostHasStrayBrackets(host string) bool {\n    if strings.HasPrefix(host, \"[\") && strings.Contains(host, \"]\") {\n        return false // legit IPv6 literal form\n    }\n    return strings.ContainsAny(host, \"[]\")\n}","typeGuard":null,"tryCatchPattern":"var u uri.URI\nif err := u.Parse(nil, nil, raw); err != nil {\n    if strings.HasPrefix(err.Error(), \"invalid host\") {\n        return fmt.Errorf(\"rejecting bad host: %w\", err) // map to 400\n    }\n    return err\n}","preventionTips":["Escape or strip brackets before placing values into host position","Validate Host headers at the proxy edge with a strict host regex","Keep IPv6 handling explicit: bracketed literals only in the host slot"],"tags":["uri","parsing","host","validation"],"backgroundTag":"invalid-uri-host","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}