{"record":{"id":"2cddf900853ca3e8","repo":"goharbor/harbor","slug":"nil-request","errorCode":null,"errorMessage":"nil request","messagePattern":"nil request","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/jobservice/api/authenticator.go","lineNumber":51,"sourceCode":"// Authenticator defined behaviors of doing auth checking.\ntype Authenticator interface {\n\t// Auth incoming request\n\t//\n\t// req *http.Request: the incoming request\n\t//\n\t// Returns:\n\t// nil returned if successfully done\n\t// otherwise an error returned\n\tDoAuth(req *http.Request) error\n}\n\n// SecretAuthenticator implements interface 'Authenticator' based on simple secret.\ntype SecretAuthenticator struct{}\n\n// DoAuth implements same method in interface 'Authenticator'.\nfunc (sa *SecretAuthenticator) DoAuth(req *http.Request) error {\n\tif req == nil {\n\t\treturn errors.New(\"nil request\")\n\t}\n\n\th := strings.TrimSpace(req.Header.Get(authHeader))\n\tif utils.IsEmptyStr(h) {\n\t\treturn fmt.Errorf(\"header '%s' missing\", authHeader)\n\t}\n\n\tif !strings.HasPrefix(h, secretPrefix) {\n\t\treturn fmt.Errorf(\"'%s' should start with '%s'\", authHeader, secretPrefix)\n\t}\n\n\tsecret := strings.TrimSpace(strings.TrimPrefix(h, secretPrefix))\n\t// incase both two are empty\n\tif utils.IsEmptyStr(secret) {\n\t\treturn errors.New(\"empty secret is not allowed\")\n\t}\n\n\texpectedSecret := config.GetUIAuthSecret()","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/jobservice/api/authenticator.go#L33-L69","documentation":"Jobservice SecretAuthenticator.DoAuth returns 'nil request' immediately when the *http.Request passed in is nil. It is a defensive parameter guard; in the shipped HTTP pipeline the middleware always receives a real request, so this is effectively a developer/test-path error.","triggerScenarios":"Programmatic use of SecretAuthenticator (unit tests, custom middleware) calling DoAuth(nil) a hand-written handler invoking the authenticator before building a request.","commonSituations":"Almost exclusively test code or experimental wrappers - not reachable through normal jobservice deployment.","solutions":["Pass the actual *http.Request from the handler into DoAuth","Guard at the call site: reject nil requests before authenticating","In tests, construct requests with httptest.NewRequest"],"exampleFix":"// before\n_ = sa.DoAuth(nil)\n\n// after\nreq := httptest.NewRequest(http.MethodGet, \"/api/v1/jobs\", nil)\nreq.Header.Set(\"Authorization\", \"Secret testsecret\")\nerr := sa.DoAuth(req)","handlingStrategy":"validation","validationCode":"if req == nil {\n    return errors.New(\"cannot authenticate a nil request\")\n}\nerr := sa.DoAuth(req)","typeGuard":"func isNilRequestErr(err error) bool { return err != nil && strings.Contains(err.Error(), \"nil request\") }","tryCatchPattern":"if err := sa.DoAuth(req); err != nil {\n    if strings.Contains(err.Error(), \"nil request\") {\n        return errors.New(\"programming error: request not constructed\")\n    }\n    return err\n}","preventionTips":["Never call DoAuth outside the HTTP middleware chain","Build requests with httptest.NewRequest in tests","Fail loudly on nil requests at the wrapper layer"],"tags":["harbor","jobservice","auth","nil-guard"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}