{"record":{"id":"cd6c9d2eb1b83c7a","repo":"amir20/dozzle","slug":"bad-request","errorCode":null,"errorMessage":"Bad Request","messagePattern":"Bad Request","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"internal/auth/proxy.go","lineNumber":56,"sourceCode":"}\n\nfunc NewForwardProxyAuth(userHeader, emailHeader, nameHeader, filterHeader, rolesHeader string) *proxyAuthContext {\n\treturn &proxyAuthContext{\n\t\theaderUser:   userHeader,\n\t\theaderEmail:  emailHeader,\n\t\theaderName:   nameHeader,\n\t\theaderFilter: filterHeader,\n\t\theaderRoles:  rolesHeader,\n\t}\n}\n\nfunc (p *proxyAuthContext) AuthMiddleware(next http.Handler) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tif r.Header.Get(p.headerUser) != \"\" {\n\t\t\tcontainerFilter, err := container.ParseContainerFilter(r.Header.Get(p.headerFilter))\n\t\t\tif err != nil {\n\t\t\t\tlog.Warn().Err(err).Str(\"filter\", r.Header.Get(p.headerFilter)).Msg(\"Failed to parse container filter\")\n\t\t\t\thttp.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tuserRoles := All\n\t\t\tif strings.TrimSpace(r.Header.Get(p.headerRoles)) != \"\" {\n\t\t\t\tuserRoles = ParseRole(r.Header.Get(p.headerRoles))\n\t\t\t}\n\t\t\tuser := newUser(r.Header.Get(p.headerUser), r.Header.Get(p.headerEmail), r.Header.Get(p.headerName), containerFilter, userRoles)\n\t\t\tctx := WithUser(r.Context(), user)\n\t\t\tnext.ServeHTTP(w, r.WithContext(ctx))\n\t\t} else {\n\t\t\tnext.ServeHTTP(w, r)\n\t\t}\n\t})\n}\n\nfunc (p *proxyAuthContext) CreateToken(username, password string) (string, error) {\n\tlog.Fatal().Msg(\"CreateToken not implemented in proxy auth\")\n\treturn \"\", nil","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/auth/proxy.go#L38-L74","documentation":"In forward-proxy auth, the container filter header is parsed with container.ParseContainerFilter; a malformed filter expression logs a warning and the middleware rejects the request with 400 Bad Request. It is not an authentication failure, but a malformed label-filter header from the proxy.","triggerScenarios":"Forward auth proxy (e.g. Authelia) sends a non-empty filter header that does not parse as a valid container label filter (bad syntax, unbalanced expressions, wrong key=value form).","commonSituations":"Misconfigured proxy response headers mapping the wrong upstream header into the filter slot; users crafting label expressions with typos; proxy URL-decoding mangling special characters.","solutions":["Fix the container filter expression sent by the proxy to valid key=value label syntax","Check proxy configuration (e.g. Authelia authn rules) for the header that carries the filter","Temporarily remove the filter header to confirm it is the failing part","Check Dozzle logs for the 'Failed to parse container filter' warning showing the bad value"],"exampleFix":"// before (proxy sends malformed filter)\nhttp.Header{\"X-Container-Filter\": {\"name==foo\"}}\n// after\nhttp.Header{\"X-Container-Filter\": {\"name=foo\"}}","handlingStrategy":"validation","validationCode":"const filter = req.headers['x-container-filter'];\nif (filter && !/^[\\w.-]+=(~?[\\w.*-]+|[\\w.-]+=[\\w.*-]+)(,[\\w.-]+=(~?[\\w.*-]+))*$/.test(filter)) {\n  throw new Error(`invalid container filter: ${filter}`);\n}","typeGuard":null,"tryCatchPattern":"proxy.on('proxyRes', res => {\n  const f = res.headers['x-container-filter'];\n  if (f && !isValidFilter(f)) delete res.headers['x-container-filter'];\n});","preventionTips":["Keep filter headers to simple label=value pairs","Test forward-auth header mappings with a real request","Check Dozzle's 'Failed to parse container filter' log line when tuning proxy config"],"tags":["auth","forward-proxy","bad-request","filter"],"backgroundTag":"invalid-argument-format","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}