{"record":{"id":"4548e543756b4fa5","repo":"crowdsecurity/crowdsec","slug":"invalid-rdns-regex-s-for-bot-entry-s-in-s","errorCode":null,"errorMessage":"invalid rdns regex '%s' for bot entry '%s' in %s: %w","messagePattern":"invalid rdns regex '(.+?)' for bot entry '(.+?)' in (.+?): %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/exprhelpers/botfile.go","lineNumber":112,"sourceCode":"\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\n// consistent.\nfunc parseBotAddr(s string) (netip.Addr, bool) {\n\taddr, err := netip.ParseAddr(s)\n\tif err != nil {\n\t\thost, _, splitErr := net.SplitHostPort(s)","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/exprhelpers/botfile.go#L94-L130","documentation":"Each non-empty element of the \"rdns\" array is compiled as a case-insensitive regex matched against FCrDNS-verified hostnames. This error is thrown when the pattern is not valid Go RE2 syntax. Compilation happens at load time so bad patterns abort data-file initialization with the offending pattern, entry, and file named.","triggerScenarios":"A bots JSONL entry contains \"rdns\":[...] where one pattern fails regexp.Compile: unbalanced parentheses, dangling backslash, invalid repetition like \"**\", or PCRE-only syntax such as lookaheads or backreferences that RE2 rejects.","commonSituations":"Hand-written domain regexes with typos; copying shell glob patterns (*.googlebot.com) instead of regexes; pasting PCRE patterns from other tools (grep -P, PHP); forgetting to escape dots (cosmetic but the compile error usually indicates worse).","solutions":["Fix the syntax error indicated by the wrapped regexp/syntax message (it names the position).","Convert globs to regex: *.googlebot.com becomes (^|\\.)googlebot\\.com$.","Remove RE2-unsupported constructs (lookaheads (?=...), lookbehinds, backreferences \\1) and restructure the pattern.","Anchor the pattern — (^|\\.)domain\\.tld$ — so attacker-controlled subdomain suffixes cannot match.","Test with Go: regexp.Compile(\"(?i)\" + pattern) before editing the data file."],"exampleFix":"// before\n{\"name\":\"gbot\",\"rdns\":[\"(?=.*google)\\\\1\"]}\n// after\n{\"name\":\"gbot\",\"rdns\":[\"(^|\\.)googlebot\\.com$\"]}","handlingStrategy":"validation","validationCode":"for _, p := range entry.RDNS {\n\tif _, err := regexp.Compile(\"(?i)\" + p); err != nil {\n\t\t// reject before FileInit\n\t}\n}\nvalid := err == nil","typeGuard":null,"tryCatchPattern":"if err := exprhelpers.FileInit(botFile, \"bots\"); err != nil {\n\tif strings.Contains(err.Error(), \"invalid rdns regex\") {\n\t\tlog.Errorf(\"offending rdns pattern: %v\", err)\n\t}\n\treturn err\n}","preventionTips":["Use the canonical anchored form (^|\\.)domain\\.tld$ for every rdns pattern.","Escape dots in domain names (\\. not .).","Avoid PCRE-only syntax; test with regexp.Compile in CI.","Convert globs (*.example.com) to regexes rather than pasting them directly."],"tags":["go","regex","rdns","validation"],"backgroundTag":"invalid-regex-pattern","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"}