{"record":{"id":"4b2b4bcea2c061a1","repo":"ruvnet/ruflo","slug":"pattern-rejected-nested-quantifiers-detected-pot","errorCode":null,"errorMessage":"Pattern rejected: nested quantifiers detected (potential ReDoS): ${pattern}","messagePattern":"Pattern rejected: nested quantifiers detected \\(potential ReDoS\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/guidance/src/authority.ts","lineNumber":672,"sourceCode":"        return this.costlyReversiblePatterns.map(p => p.source);\n      case 'reversible':\n        return this.reversiblePatterns.map(p => p.source);\n    }\n  }\n\n  /**\n   * Add a pattern to a classification.\n   *\n   * Validates the pattern against ReDoS heuristics before accepting it.\n   * Rejects patterns with nested quantifiers (e.g., `(a+)+`) that can\n   * cause catastrophic backtracking.\n   *\n   * @throws Error if the pattern is invalid regex or contains ReDoS-prone constructs\n   */\n  addPattern(classification: IrreversibilityClass, pattern: string): void {\n    // ReDoS heuristic: reject nested quantifiers like (a+)+, (a*)+, (a+)*, etc.\n    if (/([+*]|\\{[0-9]+,?\\})\\s*\\)[\\s]*[+*]|\\{[0-9]+,?\\}/.test(pattern)) {\n      throw new Error(`Pattern rejected: nested quantifiers detected (potential ReDoS): ${pattern}`);\n    }\n    // Also reject patterns longer than 500 chars as a sanity bound\n    if (pattern.length > 500) {\n      throw new Error(`Pattern rejected: exceeds maximum length of 500 characters`);\n    }\n\n    const regex = new RegExp(pattern, 'i');\n\n    switch (classification) {\n      case 'irreversible':\n        this.irreversiblePatterns.push(regex);\n        break;\n      case 'costly-reversible':\n        this.costlyReversiblePatterns.push(regex);\n        break;\n      case 'reversible':\n        this.reversiblePatterns.push(regex);\n        break;","sourceCodeStart":654,"sourceCodeEnd":690,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/guidance/src/authority.ts#L654-L690","documentation":"MemoryAuthority.addPattern() compiles caller-supplied regexes into irreversibility classifications, so it screens them for catastrophic-backtracking constructs first. Nested quantifiers such as `(a+)+`, `(a*)*`, or `(\\w+){2,}*` can turn an adversarial subject string into exponential CPU time (ReDoS), and because these patterns run over memory-change descriptions they are rejected before `new RegExp` ever runs. The heuristic test itself is a regex over the pattern text.","triggerScenarios":"addPattern('irreversible', '(a+)+'); any pattern where a quantifier (+, *, or {n,}) immediately follows a group that itself contains a quantifier, e.g. '(\\\\w+)*', '(.|a)+*'; feeding unvetted patterns sourced from user input or LLM output.","commonSituations":"Auto-generating classification patterns from logs or model output; copy-pasting a regex from an answer site that uses nested quantifiers; converting a glob or fuzzy matcher to regex and accidentally nesting repetition.","solutions":["Flatten the pattern: `(a+)+` → `a+`; `(\\w+)*` → `\\w*`","Use a single bounded repetition: `(?:ab){1,10}` instead of `(ab+)+`","Validate patterns against the same heuristic in your test suite before shipping them to production","If the construct is unavoidable, pre-filter input length so backtracking is bounded"],"exampleFix":"// before\nauthority.addPattern('irreversible', '(a+)+b'); // throws ReDoS rejection\n\n// after\nauthority.addPattern('irreversible', 'a+b'); // no nested quantifier","handlingStrategy":"validation","validationCode":"const nestedQuantifier =\n  /([+*]|\\{[0-9]+,?\\})\\s*\\)[\\s]*[+*]|\\{[0-9]+,?\\}/;\nif (nestedQuantifier.test(pattern)) {\n  throw new Error(`pattern contains nested quantifiers: ${pattern}`);\n}\nauthority.addPattern(classification, pattern);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Unit-test every classification pattern against the same heuristic","Never pass user- or LLM-authored regexes straight to addPattern()","Prefer flattened patterns (a+ over (a+)+) when translating matchers"],"tags":["regex","redos","security","validation","guidance","authority"],"backgroundTag":"regex-redos-pattern","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}