{"record":{"id":"5c2e6c8278801356","repo":"valyala/fasthttp","slug":"forbidden-trailer-key-q","errorCode":null,"errorMessage":"forbidden trailer key %q","messagePattern":"forbidden trailer key %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"header.go","lineNumber":2747,"sourceCode":"}\n\nfunc parseTrailer(src []byte, dest []argsKV, disableNormalizing bool) ([]argsKV, int, error) {\n\tvar s headerScanner\n\ts.b = src\n\n\tfor s.next() {\n\t\t// Trim trailing whitespace before the colon to normalize headers\n\t\t// like \"Content-Length :\" to \"Content-Length:\".\n\t\ts.key = trimTrailingSpace(s.key)\n\n\t\tif len(s.key) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\t// Key bytes were already validated by the scanner.\n\t\tdisable := disableNormalizing || s.keyHasSpace\n\t\t// Forbidden by RFC 7230, section 4.1.2\n\t\tif isBadTrailer(s.key) {\n\t\t\treturn dest, 0, fmt.Errorf(\"forbidden trailer key %q\", s.key)\n\t\t}\n\t\tfor _, ch := range s.value {\n\t\t\tif !validHeaderValueByte(ch) {\n\t\t\t\treturn dest, 0, fmt.Errorf(\"invalid trailer value %q\", s.value)\n\t\t\t}\n\t\t}\n\t\tnormalizeHeaderKeyValidated(s.key, disable)\n\t\tdest = appendArgBytes(dest, s.key, s.value, argsHasValue)\n\t}\n\tif s.err != nil {\n\t\treturn dest, 0, s.err\n\t}\n\treturn dest, s.r, nil\n}\n\nfunc isBadTrailer(key []byte) bool {\n\tif len(key) == 0 {\n\t\treturn true","sourceCodeStart":2729,"sourceCodeEnd":2765,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/header.go#L2729-L2765","documentation":"Chunked-transfer trailer keys are validated against RFC 7230 §4.1.2: only header fields explicitly permitted for trailers may appear. fasthttp throws this when a trailer key is in the forbidden set (e.g. Transfer-Encoding, Content-Length, Host, Trailer itself).","triggerScenarios":"Reading a request or response with chunked transfer encoding whose trailer section contains a key matched by isBadTrailer — during header trailer parsing (readTrailer).","commonSituations":"Misbehaving HTTP clients or proxies emitting forbidden end-of-body trailer fields; hand-rolled HTTP senders appending hop-by-hop headers as trailers; fuzzers.","solutions":["Fix the sender to omit forbidden headers from the trailer section (send them before the body instead)","Reject the request at an upstream proxy that sanitizes trailers","If you control the client library, upgrade it — older stacks may emit non-compliant trailers"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var forbiddenTrailers = map[string]bool{\n    \"transfer-encoding\": true, \"content-length\": true, \"host\": true,\n    \"trailer\": true, \"te\": true, \"connection\": true,\n}\n// validate before sending trailers from your own client\nfunc trailerKeyAllowed(k string) bool { return !forbiddenTrailers[strings.ToLower(k)] }","typeGuard":null,"tryCatchPattern":"if err := h.Read(br); err != nil && strings.Contains(err.Error(), \"forbidden trailer key\") {\n    http.Error(w, \"bad trailer\", fasthttp.StatusBadRequest)\n    return\n}","preventionTips":["Only emit RFC 7230-allowed trailer fields (e.g. checksums, grading metadata)","Announce trailers via the Trailer header before the body","Sanitize trailers at edge proxies","Keep client HTTP stacks up to date"],"tags":["http","trailer","rfc7230","fasthttp"],"backgroundTag":"invalid-http-trailer","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}