Root cause
Resource abuse & availability
fix: prevent ReDoS in HTMLInputElement pattern validation
How AI contributed: Flawed AI-written codePublished Jul 2, 2026 in
asymmetric-effort/nogginlessdomAll 2 findings in this repository
NogginLessDom compiles a page-assigned input pattern straight into a regular expression whenever a validity flag, checkValidity() or reportValidity() is read, with no bound on how long matching can run. A Claude-assisted fix added a 1,024-character cap and a narrow nested-quantifier check, but overlapping alternations and grouped repetitions still pass the check and backtrack exponentially, so a hostile pattern can still freeze the event loop. No later release closes the sink.
Root cause
fix: prevent ReDoS in HTMLInputElement pattern validation
Fix status
No minimum fix commit has been established for this finding.
Fix status unresolved
Case facts
@@ -5,6 +5,16 @@ import { Element, Event, Node } from './index.js'; +/**+ * Detect nested quantifiers that can cause catastrophic backtracking.+ * Matches patterns like (a+)+, (a*)+, (a+)*, etc.+ */+function hasNestedQuantifiers(pattern: string): boolean {+ return (+ /([+*])\s*[)]\s*[+*{]/.test(pattern) || /([+*])\s*\}\s*[+*{]/.test(pattern)+ );+}+ // Helper to collect descendants by tag function collectDescendants(root: Node, tagName: string): Element[] { const results: Element[] = [];@@ -281,12 +291,20 @@ export class HTMLInputElement extends Element { } let patternMismatch = false;+ const MAX_PATTERN_LENGTH = 1024; if (this.pattern !== '' && this.value !== '') {- try {- const re = new RegExp(`^(?:${this.pattern})$`);- patternMismatch = !re.test(this.value);- } catch {+ if (+ this.pattern.length > MAX_PATTERN_LENGTH ||+ hasNestedQuantifiers(this.pattern)+ ) { patternMismatch = false;+ } else {+ try {+ const re = new RegExp(`^(?:${this.pattern})$`);+ patternMismatch = !re.test(this.value);+ } catch {+ patternMismatch = false;+ } } }