HarperFast / HarperFast/harper
[security] ReDoS: attacker-controlled SQL LIKE pattern compiled to an unbounded per-row regex
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
**Severity:** MEDIUM · **Category:** `redos` · **CWE-1333**
**Location:** `sqlEngine/expressions/compile.ts:306` in `likeToRegex`
## Impact
A single crafted query hangs the Node worker's event loop for seconds-to-effectively-forever, denying service to every other request handled by that worker; repeated queries wedge the process.
## Details
The untrusted LIKE pattern from a request's WHERE clause is turned into a RegExp with %→.* and no length or quantifier sanitization (the '*' metacharacter is not even escaped), then run per row via re.test, so a crafted pattern causes catastrophic backtracking that blocks the worker.
## Exploit scenario
An authenticated user issues SELECT * FROM data.t WHERE name LIKE '%_%_%_%_%_%_%_%_%_%_%_%_%_%_Z' after inserting a row whose name is a long run of non-'Z' characters. likeToRegex yields ^.*..*..*...Z$ and re.test backtracks catastrophically, pinning a CPU and blocking the worker while it evaluates the filter.
## Preconditions
- sql.engine is 'auto' (default) or 'new' so the new engine plans the query
- requester is authenticated with permission to run a SELECT/UPDATE/DELETE whose WHERE contains a LIKE
- the compared column value is long enough (attacker can INSERT one) for backtracking to blow up
## Recommended fix
Escape '*' along with the other metacharacters, cap the pattern length, and compile the regex once outside the per-row eval (hoist likeToRegex out of the row closure). Prefer a non-backtracking matcher or a linear LIKE implementation, and reject patterns that expand beyond a safe bound.
---
Found by an automated multi-agent security review (Claude Security) against `origin/main` @ `2615b092b`, confirmed by a three-lens verification panel. Line numbers are as of that commit. No code was executed; derived from source review, so validate before remediation.
Contributor guide
Research direction
Start in sqlEngine/expressions/compile.ts at likeToRegex around line 306, then trace how the compiled expression is evaluated per row. Validate the reported LIKE-to-RegExp behavior and choose a bounded, non-backtracking or linear matching approach. Done means attacker-controlled patterns cannot cause catastrophic backtracking or repeated per-row compilation while LIKE queries retain their expected behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, sql, typescript
- Domain
- backend, databases, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100