{"record":{"id":"72f092ccfe2c1d96","repo":"valyala/fasthttp","slug":"fasthttp-duplicate-content-length-header","errorCode":null,"errorMessage":"fasthttp: duplicate content-length header","messagePattern":"fasthttp: duplicate content-length header","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"header.go","lineNumber":478,"sourceCode":"// 5. response control data (e.g., see Section 7.1 of [RFC7231]),\n// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)\n//\n// Return ErrBadTrailer if contain any forbidden trailers.\nfunc (h *header) AddTrailer(trailer string) error {\n\treturn h.AddTrailerBytes(s2b(trailer))\n}\n\nvar (\n\tErrBadTrailer                    = errors.New(\"fasthttp: contain forbidden trailer\")\n\tErrReadingResponseHeaders        = errors.New(\"fasthttp: error when reading response headers\")\n\tErrReadingResponseTrailer        = errors.New(\"fasthttp: error when reading response trailer\")\n\tErrResponseFirstLineMissingSpace = errors.New(\"fasthttp: cannot find whitespace in the first line of response\")\n\tErrUnexpectedStatusCodeChar      = errors.New(\"fasthttp: unexpected char at the end of status code\")\n\tErrMissingRequestMethod          = errors.New(\"fasthttp: cannot find http request method\")\n\tErrUnsupportedRequestMethod      = errors.New(\"fasthttp: unsupported http request method\")\n\tErrExtraWhitespaceInRequestLine  = errors.New(\"fasthttp: extra whitespace in request line\")\n\tErrEmptyRequestURI               = errors.New(\"fasthttp: requesturi cannot be empty\")\n\tErrDuplicateContentLength        = errors.New(\"fasthttp: duplicate content-length header\")\n\tErrUnsupportedTransferEncoding   = errors.New(\"fasthttp: unsupported transfer-encoding\")\n\tErrNonNumericChars               = errors.New(\"fasthttp: non-numeric chars found\")\n\tErrNeedMore                      = errors.New(\"fasthttp: need more data: cannot find trailing lf\")\n\tErrSmallReadBuffer               = errors.New(\"fasthttp: small read buffer. increase readbuffersize\")\n)\n\n// AddTrailerBytes add Trailer header value for chunked response\n// to indicate which headers will be sent after the body.\n//\n// Use Set to set the trailer header later.\n//\n// Trailers are only supported with chunked transfer.\n// Trailers allow the sender to include additional headers at the end of chunked messages.\n//\n// The following trailers are forbidden:\n// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),\n// 2. routing (e.g., Host),\n// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/header.go#L460-L496","documentation":"HTTP messages must carry at most one Content-Length header. When parsing headers fasthttp detects a second Content-Length and returns ErrDuplicateContentLength, since duplicates can desynchronize body framing and are a classic request-smuggling vector. The error surfaces from Response/Request Read header parsing.","triggerScenarios":"Response.Read / Request.Read / Client.Do on a message containing two Content-Length headers (e.g. 'Content-Length: 5' twice), commonly produced by misconfigured proxies or by manually appending the header twice via req.Header.SetContentLength followed by h.Add(\"Content-Length\", ...).","commonSituations":"Front-end and back-end proxies both injecting Content-Length; hand-rolled clients that set the header explicitly while fasthttp also computes it; malicious traffic probing for smuggling vulnerabilities.","solutions":["Remove the duplicate injection: set Content-Length only once — prefer header.SetContentLength(len(body)) and never also Add(\"Content-Length\", ...).","Fix intermediate proxies to not add a second Content-Length when one exists.","Strip the header before forwarding: use h.Del(\"Content-Length\") / h.SetContentLength(-1) for chunked transfer instead.","Treat incoming duplicate headers from untrusted peers as a security event and reject the connection (fasthttp already aborts the parse)."],"exampleFix":"// before\nreq.Header.SetContentLength(len(body))\nreq.Header.Add(\"Content-Length\", strconv.Itoa(len(body))) // duplicate\n// after\nreq.Header.SetContentLength(len(body))","handlingStrategy":"type-guard","validationCode":"// Before sending, ensure only fasthttp manages framing:\nreq.Header.Del(\"Content-Length\")\nreq.Header.SetContentLength(len(body)) // single authoritative setter","typeGuard":"func isDuplicateContentLength(err error) bool {\n    return err == fasthttp.ErrDuplicateContentLength\n}","tryCatchPattern":"if err := resp.Read(r); err == fasthttp.ErrDuplicateContentLength {\n    return fmt.Errorf(\"upstream sent duplicate Content-Length (possible smuggling attempt): %w\", err)\n}","preventionTips":["Never call Header.Add(\"Content-Length\", ...) — use SetContentLength only.","When forwarding headers, strip Content-Length/Transfer-Encoding and let fasthttp recompute framing.","Check proxy chains for components that append Content-Length to already-framed messages.","Alert on inbound occurrences — duplicates from untrusted peers are a smuggling probe."],"tags":["http","fasthttp","header-parsing","security"],"backgroundTag":"duplicate-content-length-header","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}