txthinking/brook · error

Invalid Request

Error message

Invalid Request

What it means

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.

Source

Thrown at socks5tohttp.go:114

	b := make([]byte, 0, 1024)
	for {
		var b1 [1024]byte
		n, err := c.Read(b1[:])
		if err != nil {
			return err
		}
		b = append(b, b1[:n]...)
		if bytes.Contains(b, []byte{0x0d, 0x0a, 0x0d, 0x0a}) {
			break
		}
		if len(b) >= 2083+18 {
			return errors.New("HTTP header too long")
		}
	}

	bb := bytes.SplitN(b, []byte(" "), 3)
	if len(bb) != 3 {
		return errors.New("Invalid Request")
	}
	method, address := string(bb[0]), string(bb[1])
	var addr string
	if method == "CONNECT" {
		addr = address
	}
	if method != "CONNECT" {
		var err error
		addr, err = GetAddressFromURL(address)
		if err != nil {
			return err
		}
	}

	tmp, err := s.Dial.Dial("tcp", addr)
	if err != nil {
		return err
	}

View on GitHub (pinned to 5cd13ef3b1)

Solutions

  1. Ensure the client sends an HTTP/1.1 request with a full 3-token request line (method SP absolute-URI SP HTTP/1.x)
  2. Do not send TLS or HTTP/2 traffic through this bridge - it only parses HTTP/1.x plaintext
  3. For CONNECT, send 'CONNECT host:port HTTP/1.1' exactly
  4. Capture a hex dump of the first bytes the client sends to confirm the wire format

Example fix

// before: HTTP/2 preface confuses the parser
client := &http2.Transport{}

// after: force HTTP/1.1 with absolute-form URI
client := &http.Transport{}
req, _ := http.NewRequest("GET", "http://target.example/path", nil)
Defensive patterns

Strategy: validation

Validate before calling

func isWellFormedRequestLine(line string) bool {
	parts := strings.SplitN(line, " ", 3)
	return len(parts) == 3 &&
		parts[0] != "" && parts[1] != "" &&
		strings.HasPrefix(parts[2], "HTTP/1.")
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of txthinking/brook@5cd13ef3b1 (2026-09-06). Data as JSON: /api/errors/ac39bff7c8a23323. Report an issue: GitHub.