crowdsecurity/crowdsec · error

multiple headers with name %s found

Error message

multiple headers with name %s found

What it means

While resolving an apiKey security scheme located in a header, the named header appeared more than once in the incoming HTTP request. The validator refuses to guess which value is the token, so API-key extraction fails and the request is treated as failing the security requirement.

Source

Thrown at pkg/appsec/api_validation/api_validation.go:267

			switch input.SecurityScheme.In {
			case "query":
				//Because we are checking for the presence of the API key, it probably does not matter if go drops parameters using ; as a separator
				values := input.RequestValidationInput.Request.URL.Query()[input.SecurityScheme.Name]
				if len(values) == 0 {
					return fmt.Errorf("query parameter %s not found", input.SecurityScheme.Name)
				}
				if len(values) > 1 {
					return fmt.Errorf("multiple query parameters with name %s found", input.SecurityScheme.Name)
				}
				authTokenValue = values[0]
			case "header":
				canonicalHeaderName := http.CanonicalHeaderKey(input.SecurityScheme.Name)
				values := input.RequestValidationInput.Request.Header[canonicalHeaderName]
				if len(values) == 0 {
					return fmt.Errorf("header %s not found", input.SecurityScheme.Name)
				}
				if len(values) > 1 {
					return fmt.Errorf("multiple headers with name %s found", input.SecurityScheme.Name)
				}
				authTokenValue = values[0]
			case "cookie":
				cookieValues := input.RequestValidationInput.Request.CookiesNamed(input.SecurityScheme.Name)
				if len(cookieValues) == 0 {
					return fmt.Errorf("cookie %s not found", input.SecurityScheme.Name)
				}
				if len(cookieValues) > 1 {
					return fmt.Errorf("multiple cookies with name %s found", input.SecurityScheme.Name)
				}
				authTokenValue = cookieValues[0].Value
			default:
				return fmt.Errorf("unsupported apiKey location %s", input.SecurityScheme.In)
			}
		case "oauth2", "openIdConnect":
			if unsupportedPolicy == PolicyIgnore {
				return nil
			}

View on GitHub (pinned to 909b515798)

Solutions

  1. Send the auth header exactly once per request.
  2. Use Header.Set instead of Header.Add in client code to avoid duplicates.
  3. Audit proxy/middleware chains for headers being merged or re-added.

Example fix

// before
req.Header.Add("X-API-Key", k1)
req.Header.Add("X-API-Key", k2)
// after
req.Header.Set("X-API-Key", k1)
Defensive patterns

Strategy: validation

Validate before calling

if len(req.Header.Values("X-API-Key")) != 1 { return errors.New("X-API-Key must be set exactly once") }

Try / catch

err := validator.ValidateRequest(input); if err != nil { if strings.Contains(err.Error(), "multiple headers") { return ErrDuplicateHeader } return err }

Prevention

When it happens

Trigger: A validated request contains two or more headers with the securityScheme's name (len(values) > 1) at pkg/appsec/api_validation/api_validation.go:267.

Common situations: Duplicate headers from a proxy adding its own copy; client library appending instead of setting the header; smuggling/HPP test probes.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/0b7f5a32978be577. Report an issue: GitHub.