{"record":{"id":"4b761fe12e45da9b","repo":"crowdsecurity/crowdsec","slug":"empty-rdns-pattern-for-bot-entry-s-in-s","errorCode":null,"errorMessage":"empty rdns pattern for bot entry '%s' in %s","messagePattern":"empty rdns pattern for bot entry '(.+?)' in (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/exprhelpers/botfile.go","lineNumber":107,"sourceCode":"\t\t}\n\n\t\tentry.ipSet[addr.Unmap()] = struct{}{}\n\t}\n\n\tfor _, r := range entry.Ranges {\n\t\tprefix, err := netip.ParsePrefix(r)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"invalid CIDR range '%s' for bot entry '%s' in %s: %w\", r, entry.Name, filename, err)\n\t\t}\n\n\t\tentry.prefixes = append(entry.prefixes, prefix.Masked())\n\t}\n\n\tfor _, p := range entry.RDNS {\n\t\t// an empty pattern matches every PTR-confirmed host: almost\n\t\t// certainly a mistake, reject it\n\t\tif p == \"\" {\n\t\t\treturn fmt.Errorf(\"empty rdns pattern for bot entry '%s' in %s\", entry.Name, filename)\n\t\t}\n\n\t\tre, err := compileBotRegex(p)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"invalid rdns regex '%s' for bot entry '%s' in %s: %w\", p, entry.Name, filename, err)\n\t\t}\n\n\t\tentry.rdnsRegexes = append(entry.rdnsRegexes, re)\n\t}\n\n\tdataFileBots[filename] = append(dataFileBots[filename], entry)\n\n\treturn nil\n}\n\n// parseBotAddr normalizes a source address as found in HTTP contexts:\n// bare IP, \"ip:port\", \"[v6]:port\". The zone is stripped and IPv4-mapped\n// IPv6 is unmapped so comparisons against load-time-parsed IPs/ranges are","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/exprhelpers/botfile.go#L89-L125","documentation":"Entries in the \"rdns\" array are regexes matched against forward-confirmed reverse-DNS names. botFileInit explicitly rejects an empty string pattern because an empty regex matches every PTR-confirmed host — almost certainly a configuration mistake that would mark all rDNS-resolvable clients as the bot. This guard fails the load instead.","triggerScenarios":"A bots JSONL entry has \"rdns\":[\"\"] or \"rdns\":[\"\", \"(^|\\.)example\\.com$\"] — any empty string element triggers the error for that entry.","commonSituations":"A templating/generation script left an empty pattern where a domain should have been substituted; hand-editing removed the pattern but kept the empty quotes; copying a list where a blank line became an empty array element.","solutions":["Replace the empty string with an anchored regex for the operator's domain, e.g. \"(^|\\.)googlebot\\.com$\".","Delete the empty element from the rdns array if it is stray.","If rDNS matching is not needed, remove the rdns field entirely and rely on ips/ranges (at least one identity source must remain, or error 1042 fires).","Check your generator script for an unset variable producing \"\" in the output."],"exampleFix":"// before\n{\"name\":\"bingbot\",\"rdns\":[\"\"]}\n// after\n{\"name\":\"bingbot\",\"rdns\":[\"(^|\\.)bing\\.com$\"]}","handlingStrategy":"validation","validationCode":"for _, p := range entry.RDNS {\n\tif strings.TrimSpace(p) == \"\" {\n\t\t// reject before FileInit: empty rdns pattern matches every PTR-confirmed host\n\t}\n}\nvalid := !hasEmpty","typeGuard":null,"tryCatchPattern":"if err := exprhelpers.FileInit(botFile, \"bots\"); err != nil {\n\tif strings.Contains(err.Error(), \"empty rdns pattern\") {\n\t\tlog.Errorf(\"fill in the rdns pattern: %v\", err)\n\t}\n\treturn err\n}","preventionTips":["Never emit empty strings into rdns arrays from generator scripts; skip empty values instead.","Always give each rdns element an anchored domain regex.","If a template variable can be empty, validate it before rendering the entry.","Remove the rdns field entirely when rDNS matching is not intended."],"tags":["go","rdns","validation","data-files"],"backgroundTag":"empty-required-field","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}