{"record":{"id":"ac39bff7c8a23323","repo":"txthinking/brook","slug":"invalid-request","errorCode":null,"errorMessage":"Invalid Request","messagePattern":"Invalid Request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"socks5tohttp.go","lineNumber":114,"sourceCode":"\tb := make([]byte, 0, 1024)\n\tfor {\n\t\tvar b1 [1024]byte\n\t\tn, err := c.Read(b1[:])\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tb = append(b, b1[:n]...)\n\t\tif bytes.Contains(b, []byte{0x0d, 0x0a, 0x0d, 0x0a}) {\n\t\t\tbreak\n\t\t}\n\t\tif len(b) >= 2083+18 {\n\t\t\treturn errors.New(\"HTTP header too long\")\n\t\t}\n\t}\n\n\tbb := bytes.SplitN(b, []byte(\" \"), 3)\n\tif len(bb) != 3 {\n\t\treturn errors.New(\"Invalid Request\")\n\t}\n\tmethod, address := string(bb[0]), string(bb[1])\n\tvar addr string\n\tif method == \"CONNECT\" {\n\t\taddr = address\n\t}\n\tif method != \"CONNECT\" {\n\t\tvar err error\n\t\taddr, err = GetAddressFromURL(address)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\ttmp, err := s.Dial.Dial(\"tcp\", addr)\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/txthinking/brook/blob/5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8/socks5tohttp.go#L96-L132","documentation":"After reading the full HTTP header, the bridge splits the request line on spaces expecting exactly 3 parts (method, address, protocol) via bytes.SplitN(b, \" \", 3). If the split does not yield 3 elements, the request line is malformed and the request is rejected as invalid. This is a sanity check before method/address extraction.","triggerScenarios":"Handle() receives data whose first line is not a well-formed HTTP request line like 'GET http://host/path HTTP/1.1' - e.g. a TLS ClientHello, raw SOCKS data, HTTP/2 preface 'PRI * HTTP/2.0', or an empty/garbage stream.","commonSituations":"Pointing a plain-HTTP-only bridge at an HTTPS (TLS) client; an HTTP/2 client connecting without downgrade; a client sending a request line with a missing target or protocol token; binary garbage on the port.","solutions":["Ensure the client sends an HTTP/1.1 request with a full 3-token request line (method SP absolute-URI SP HTTP/1.x)","Do not send TLS or HTTP/2 traffic through this bridge - it only parses HTTP/1.x plaintext","For CONNECT, send 'CONNECT host:port HTTP/1.1' exactly","Capture a hex dump of the first bytes the client sends to confirm the wire format"],"exampleFix":"// before: HTTP/2 preface confuses the parser\nclient := &http2.Transport{}\n\n// after: force HTTP/1.1 with absolute-form URI\nclient := &http.Transport{}\nreq, _ := http.NewRequest(\"GET\", \"http://target.example/path\", nil)","handlingStrategy":"validation","validationCode":"func isWellFormedRequestLine(line string) bool {\n\tparts := strings.SplitN(line, \" \", 3)\n\treturn len(parts) == 3 &&\n\t\tparts[0] != \"\" && parts[1] != \"\" &&\n\t\tstrings.HasPrefix(parts[2], \"HTTP/1.\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Force clients to HTTP/1.1 (disable HTTP/2 and TLS for this hop)","Use absolute-form URIs through proxies","Sanity-check the first bytes of the stream before parsing","Use CONNECT host:port HTTP/1.1 for tunneling"],"tags":["http","proxy","malformed-request"],"backgroundTag":"malformed-http-request","analyzedSha":"5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8","analyzedAt":"2026-09-06T04:35:00.432Z","contentChangedAt":"2026-09-06T04:35:00.432Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}