other
- Location
scripts/notionctl.mjs:973- Finding
Unbounded User-Supplied Regular Expression Enables CLI Denial of Service
- Content
View full analysis
Vulnerability Details
File Location:
scripts/notionctl.mjs, lines 973–978
Vulnerability Type: Regular Expression Denial of Service (ReDoS)
Risk Level: MediumVulnerable Code
javascript function ruleMatchesTitle(rule, title) { const m = rule.match; if (!m || !title) return false; if (m.title_regex) { const re = new RegExp(m.title_regex); return re.test(title); } if (m.contains) return title.toLowerCase().includes(String(m.contains).toLowerCase()); return false; }Technical Analysis
The
triagecommand loads rules from a caller-selected JSON file and passes each rule'stitle_regexvalue directly to the JavaScriptRegExpconstructor. The resulting expression is evaluated against Notion child-page titles without validation, complexity limits, or an execution timeout.JavaScript's backtracking regular-expression engine can consume excessive CPU when evaluating expressions containing nested or ambiguous quantifiers. For example, a rule containing
^(a+)+$can take exponentially longer to reject a sufficiently long title consisting of repeatedacharacters followed by a nonmatching character.This issue is particularly relevant in an agent workflow because a rules file in a workspace may be treated as configuration even when its contents originated from an untrusted repository or other external source. Notion page titles are also remote content and should not be assumed trustworthy.
The regular expression is created and evaluated once for each candidate rule and child page. Consequently, a malicious expression can repeatedly block the Node.js event loop during triage.
The separately flagged sensitive network behavior is not itself a vulnerability:
scripts/notionctl.mjssends the Notion API token in anAuthorization: Bearerheader only to the fixed HTTPS originhttps://api.notion.com. Sending that credential and user-selected note content to Notion is ne ...[truncated 2291 chars]- Remediation
View remediation
Remediation Suggestions
-
Avoid arbitrary regular expressions where possible. Prefer literal matching operations such as
contains,starts_with, orequals, which have predictable runtime behavior. -
Validate patterns before use. Reject expressions containing risky constructs such as nested quantifiers, ambiguous alternations, excessive repetition, backreferences, or patterns above a small length limit. A regex safety analyzer can provide defense in depth, although static analysis alone should not be treated as a complete guarantee.
-
Use a linear-time regular-expression implementation. Evaluate configurable patterns through an RE2-compatible library rather than JavaScript's backtracking engine. Document any syntax differences and reject unsupported expressions clearly.
-
Isolate evaluation if arbitrary JavaScript-compatible regex syntax must be retained. Perform matching in a worker thread or subprocess with strict CPU and wall-clock limits. Terminate the worker when a match exceeds its budget. A promise timeout in the main thread is insufficient because synchronous
RegExp.testblocks the event loop. -
Limit input size and processing scope. Apply conservative maximum lengths to both
title_regexvalues and page titles before matching. Retain the existing--limitbehavior, validate that it is finite and positive, and impose a hard upper bound. -
Treat rules as executable policy. Require explicit operator approval before consuming rules from repositories, downloaded archives, or other untrusted workspaces. Resolve rules files against an approved directory where appropriate.
-
Handle invalid patterns safely. Catch
RegExpconstruction errors per rule, report the rejected rule, and continue or abort deterministically rather than allowing malformed configuration to terminate the entire command.
-
