Validate request URI format during header parsing to reject malformed requests (#2168)

This commit is contained in:
Erik Dubbelboer
2026-03-28 11:10:23 +09:00
committed by GitHub
parent 3c43293b0c
commit 7d90713bda
2 changed files with 31 additions and 0 deletions
+30
View File
@@ -2866,6 +2866,13 @@ func (h *RequestHeader) parseFirstLine(buf []byte) (int, error) {
return 0, fmt.Errorf("requestURI cannot be empty in %q", buf)
}
if err := validateRequestURI(h.method, b[:n]); err != nil {
if h.secureErrorLogMessage {
return 0, fmt.Errorf("invalid requestURI %q", b[:n])
}
return 0, fmt.Errorf("invalid requestURI %q in %q: %w", b[:n], buf, err)
}
// Check for extra whitespace - only one space should separate URI from HTTP version
if n+1 < len(b) && b[n+1] == ' ' {
if h.secureErrorLogMessage {
@@ -2903,6 +2910,29 @@ func (h *RequestHeader) parseFirstLine(buf []byte) (int, error) {
return len(buf) - len(bNext), nil
}
func validateRequestURI(method, requestURI []byte) error {
if stringContainsCTLByte(requestURI) {
return ErrorInvalidURI
}
if len(requestURI) == 1 && requestURI[0] == '*' {
return nil
}
if len(requestURI) > 0 && requestURI[0] == '/' {
return nil
}
if before, _, ok := bytes.Cut(requestURI, strColonSlashSlash); ok {
if !isValidScheme(before) {
return ErrorInvalidURI
}
return nil
}
// net/http treats CONNECT request-targets without a leading slash as authority-form.
if bytes.Equal(method, strConnect) {
return nil
}
return ErrorInvalidURI
}
func readRawHeaders(dst, buf []byte) ([]byte, int, error) {
n := bytes.IndexByte(buf, nChar)
if n < 0 {
+1
View File
@@ -90,6 +90,7 @@ var (
strBytes = []byte("bytes")
strBasicSpace = []byte("Basic ")
strLink = []byte("Link")
strConnect = []byte("CONNECT")
strApplicationSlash = []byte("application/")
strImageSVG = []byte("image/svg")