{"record":{"id":"e43e6a49edab568b","repo":"crowdsecurity/crowdsec","slug":"invalid-headers","errorCode":null,"errorMessage":"invalid headers","messagePattern":"invalid headers","errorType":"http","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/acquisition/modules/http/run.go","lineNumber":42,"sourceCode":"\t\"github.com/crowdsecurity/crowdsec/pkg/pipeline\"\n)\n\nfunc authorizeRequest(r *http.Request, hc *Configuration) error {\n\tif hc.AuthType == \"basic_auth\" {\n\t\tusername, password, ok := r.BasicAuth()\n\t\tif !ok {\n\t\t\treturn errors.New(\"missing basic auth\")\n\t\t}\n\n\t\tif username != hc.BasicAuth.Username || password != hc.BasicAuth.Password {\n\t\t\treturn errors.New(\"invalid basic auth\")\n\t\t}\n\t}\n\n\tif hc.AuthType == \"headers\" {\n\t\tfor key, value := range hc.Headers {\n\t\t\tif r.Header.Get(key) != value {\n\t\t\t\treturn errors.New(\"invalid headers\")\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc rejectBody(w http.ResponseWriter, err error) error {\n\tif maxBytesErr, ok := errors.AsType[*http.MaxBytesError](err); ok {\n\t\tw.WriteHeader(http.StatusRequestEntityTooLarge)\n\t\treturn fmt.Errorf(\"body size exceeds max body size: %d\", maxBytesErr.Limit)\n\t}\n\n\tw.WriteHeader(http.StatusBadRequest)\n\n\treturn fmt.Errorf(\"failed to read body: %w\", err)\n}\n","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/http/run.go#L24-L60","documentation":"When the HTTP source is configured with auth_type: headers, authorizeRequest() (pkg/acquisition/modules/http/run.go:42) requires every configured header key/value pair to be present and equal on the incoming request. Any single mismatched or missing header causes rejection with 'invalid headers'.","triggerScenarios":"Sending a request to an http source with auth_type: headers that omits one of the configured headers or sends a different value (including case/whitespace differences for the value).","commonSituations":"Client sends fewer headers than configured; header value differs by case or whitespace; reverse proxy renames or drops custom headers (e.g. X- prefix handling); config updated with a new required header that old clients don't send.","solutions":["Send all headers exactly as configured under auth_type.headers in the source config, e.g. curl -H 'X-API-Key: value'.","Compare header names and values character-by-character (values are compared with !=, so exact match required).","Check intermediate proxies/load balancers are not stripping or renaming the custom headers.","Remove unused entries from the auth_type.headers map in the config to reduce required headers."],"exampleFix":"// before\ncurl -H 'X-API-Key: wrong' http://localhost:8080/logs\n\n// after\ncurl -H 'X-API-Key: expected-value' http://localhost:8080/logs","handlingStrategy":"validation","validationCode":"for k, v := range cfg.AuthTypeHeaders {\n    if r.Header.Get(k) != v {\n        // missing or mismatched header; fix client headers before sending\n    }\n}","typeGuard":"func hasRequiredHeaders(r *http.Request, want map[string]string) bool {\n    for k, v := range want {\n        if r.Header.Get(k) != v { return false }\n    }\n    return true\n}","tryCatchPattern":"if err := authorizeRequest(req, cfg); err != nil {\n    if err.Error() == \"invalid headers\" {\n        // diff sent headers against auth_type.headers config\n    }\n}","preventionTips":["Keep the required-headers map minimal and documented for client teams.","Test with curl -H reproducing exact key/value pairs.","Watch for proxies that strip or normalize custom headers."],"tags":["http","authentication","headers"],"backgroundTag":"authentication-required","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}