{"record":{"id":"42cddaf1f2636d7b","repo":"crowdsecurity/crowdsec","slug":"unauthorized","errorCode":null,"errorMessage":"unauthorized","messagePattern":"unauthorized","errorType":"http","errorClass":null,"httpStatus":401,"severity":"error","filePath":"pkg/cticlient/client.go","lineNumber":23,"sourceCode":"\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/crowdsecurity/crowdsec/pkg/apiclient/useragent\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nconst (\n\tCTIBaseUrl    = \"https://cti.api.crowdsec.net/v2\"\n\tsmokeEndpoint = \"/smoke\"\n\tfireEndpoint  = \"/fire\"\n)\n\nvar (\n\tErrUnauthorized  = errors.New(\"unauthorized\")\n\tErrLimit         = errors.New(\"request quota exceeded, please reduce your request rate\")\n\tErrNotFound      = errors.New(\"ip not found\")\n\tErrDisabled      = errors.New(\"cti is disabled\")\n\tErrUnknown       = errors.New(\"unknown error\")\n\tdefaultUserAgent = useragent.Default()\n)\n\ntype CrowdsecCTIClient struct {\n\thttpClient *http.Client\n\tapiKey     string\n\tLogger     *log.Entry\n\tUserAgent  string\n}\n\nfunc (c *CrowdsecCTIClient) doRequest(ctx context.Context, method string, endpoint string, params map[string]string) ([]byte, error) {\n\turl := CTIBaseUrl + endpoint\n\tif len(params) > 0 {\n\t\turl += \"?\"","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/cticlient/client.go#L5-L41","documentation":"ErrUnauthorized is the sentinel error returned when the CrowdSec CTI API answers HTTP 403 Forbidden, meaning the API key is rejected or lacks access to the endpoint. It is returned by doRequest and surfaced through CrowdsecCTI/Fire/GetIPInfo calls.","triggerScenarios":"Any CTI call (GetIPInfo, Fire) where the API responds with 403: invalid/expired/revoked API key, or key without entitlement for the endpoint.","commonSituations":"CTI_API_KEY set incorrectly (typo, whitespace, wrong env); key revoked in the CrowdSec console; free-tier key used against an endpoint it can't access.","solutions":["Verify the CTI API key in your config/env is correct and active in the CrowdSec console","Regenerate the API key at https://app.crowdsec.net and update your configuration","Check errors.Is(err, cticlient.ErrUnauthorized) in your caller and disable/flag CTI enrichment on auth failure"],"exampleFix":"// before\nresp, err := ctiClient.GetIPInfo(ip)\n// after\nresp, err := ctiClient.GetIPInfo(ip)\nif errors.Is(err, cticlient.ErrUnauthorized) {\n    log.Warning(\"CTI key rejected, disabling CTI enrichment\")\n}","handlingStrategy":"try-catch","validationCode":"// guard: key must be set before any CTI call\nif apiKey == \"\" { return errors.New(\"CTI API key not configured\") }","typeGuard":"null","tryCatchPattern":"resp, err := ctiClient.GetIPInfo(ip)\nif errors.Is(err, cticlient.ErrUnauthorized) {\n    // disable CTI enrichment, do not retry\n}","preventionTips":["Verify the API key in the CrowdSec console before deploying","Trim whitespace/quotes from the key in config/env","Alert on repeated 403s to catch revoked keys early"],"tags":["api","authentication","http","cti"],"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"}