{"record":{"id":"ca4329f39a68ec84","repo":"crowdsecurity/crowdsec","slug":"apikey-is-empty","errorCode":null,"errorMessage":"APIKey is empty","messagePattern":"APIKey is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apiclient/auth_key.go","lineNumber":22,"sourceCode":"\t\"errors\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\ntype APIKeyTransport struct {\n\tAPIKey string\n\t// Transport is the underlying HTTP transport to use when making requests.\n\t// It will default to http.DefaultTransport if nil.\n\tTransport     http.RoundTripper\n\tUserAgent     string\n}\n\n// RoundTrip implements the RoundTripper interface.\nfunc (t *APIKeyTransport) RoundTrip(req *http.Request) (*http.Response, error) {\n\tif t.APIKey == \"\" {\n\t\treturn nil, errors.New(\"APIKey is empty\")\n\t}\n\n\t// We must make a copy of the Request so\n\t// that we don't modify the Request we were given. This is required by the\n\t// specification of http.RoundTripper.\n\treq = cloneRequest(req)\n\treq.Header.Add(\"X-Api-Key\", t.APIKey)\n\n\tif t.UserAgent != \"\" {\n\t\treq.Header.Add(\"User-Agent\", t.UserAgent)\n\t}\n\n\tlog.Debugf(\"req-api: %s %s\", req.Method, req.URL.String())\n\n\tif log.IsLevelEnabled(log.TraceLevel) {\n\t\tdump, _ := httputil.DumpRequest(req, true)\n\t\tlog.Tracef(\"auth-api request: %s\", string(dump))\n\t}","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiclient/auth_key.go#L4-L40","documentation":"APIKeyTransport is an http.RoundTripper that injects an API key into outgoing requests. RoundTrip refuses to execute if the transport's APIKey field is empty, because a request sent without a key would fail authentication downstream anyway.","triggerScenarios":"Constructing an APIKeyTransport (or an apiclient built on one) with an empty APIKey string and then issuing any HTTP request through it.","commonSituations":"Config file missing api_key / LAPI key; environment variable not set when building the client; reading the key from a file that is empty or failed to load; registering a bouncer without supplying its key.","solutions":["Set the APIKey field on the APIKeyTransport before using the client","Load the key from config/env (e.g. LocalAPIider credentials) and validate it is non-empty at startup","Regenerate credentials with cscli (e.g. 'cscli bouncers add') and put the key in the client config"],"exampleFix":"// before\ntr := &apiclient.APIKeyTransport{Transport: base}\nclient := &http.Client{Transport: tr}\n// after\nif apiKey == \"\" {\n    return nil, fmt.Errorf(\"missing API key\")\n}\ntr := &apiclient.APIKeyTransport{APIKey: apiKey, Transport: base}\nclient := &http.Client{Transport: tr}","handlingStrategy":"validation","validationCode":"// Go: check the key before constructing the transport\nif apiKey == \"\" {\n    return nil, fmt.Errorf(\"no API key configured for LAPI client\")\n}\ntr := &apiclient.APIKeyTransport{APIKey: apiKey, Transport: http.DefaultTransport}","typeGuard":null,"tryCatchPattern":"resp, err := client.Do(req)\nif err != nil && strings.Contains(err.Error(), \"APIKey is empty\") {\n    return fmt.Errorf(\"client misconfigured: %w\", err)\n}","preventionTips":["Fail fast at startup if the configured API key is empty","Load keys from config files/env and log (without printing) their presence","Rotate and distribute keys via cscli rather than hardcoding"],"tags":["http","authentication","apiclient"],"backgroundTag":"missing-api-key","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"}