{"record":{"id":"12e0628c5774a697","repo":"tinyhumansai/openhuman","slug":"keyword-rule-regex-is-well-formed","errorCode":null,"errorMessage":"keyword rule regex is well-formed","messagePattern":"keyword rule regex is well-formed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/security/pii/rules.rs","lineNumber":37,"sourceCode":"\n/// A single detection rule: matches [`regex`](Rule::regex), attributes hits to\n/// [`category`](Rule::category), and — if present — only counts a match when\n/// [`validator`](Rule::validator) confirms it.\npub(crate) struct Rule {\n    pub category: PiiCategory,\n    pub regex: Regex,\n    /// Optional structural check applied to each raw match before it counts.\n    pub validator: Option<fn(&str) -> bool>,\n}\n\n/// Build a keyword rule: a case-insensitive, word-boundaried alternation over\n/// `terms`, all attributed to `category`.\nfn keyword_rule(category: PiiCategory, terms: &[&str]) -> Rule {\n    let alternation = terms.join(\"|\");\n    let pattern = format!(r\"(?i)\\b(?:{alternation})\\b\");\n    Rule {\n        category,\n        regex: Regex::new(&pattern).expect(\"keyword rule regex is well-formed\"),\n        validator: None,\n    }\n}\n\n/// Build a pattern rule from a raw regex string.\nfn pattern_rule(category: PiiCategory, pattern: &str, validator: Option<fn(&str) -> bool>) -> Rule {\n    Rule {\n        category,\n        regex: Regex::new(pattern).expect(\"pattern rule regex is well-formed\"),\n        validator,\n    }\n}\n\n/// Luhn checksum validation for candidate payment-card numbers. Strips\n/// separators first; requires 13–19 digits.\npub(crate) fn is_luhn_valid(raw: &str) -> bool {\n    let digits: Vec<u8> = raw\n        .bytes()","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/security/pii/rules.rs#L19-L55","documentation":"Static-invariant panic in keyword_rule(): the rule table builds case-insensitive, word-boundaried alternations from hardcoded term lists, so Regex::new can only fail on a developer mistake (unescaped regex metacharacter in a term, or an empty list producing an invalid pattern). It fires at PII-rule-table initialization, before any user data is scanned.","triggerScenarios":"Thrown at src/openhuman/security/pii/rules.rs:37 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Escape each term with regex::escape before joining with '|'","Add a unit test per rule asserting compilation so a bad term fails CI, not boot","Guard against empty term lists producing '(?i)\\b(?:)\\b'"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}