fix(security): RE2 for user-supplied regexes; resolve 4 CodeQL alerts (#152/153/155/156)#3544
Conversation
…3543) Resolves the two high-severity CodeQL js/regex-injection alerts (#153, #155) by compiling all user/admin-supplied regular expressions with RE2, a linear-time engine immune to catastrophic backtracking. The previous heuristic guards (length caps + nested-quantifier checks) reduced but could not eliminate the risk, and CodeQL (correctly) kept flagging the user→RegExp dataflow. - New src/utils/safeRegex.ts: compileUserRegex(pattern, flags) wraps RE2 and returns a RegExp-compatible matcher (test/exec/match/replace). RE2 rejects backreferences and lookaround — the intended trade-off — so callers keep their existing try/catch to treat unsupported patterns as "invalid regex". - Convert every user-supplied regex site, validation AND execution: - server.ts: remote(-localstats) name-filter validation (2 sites). - services/database.ts: the name-filter execution sites that actually match node names (traceroute + localstats union filters) — the real ReDoS surface CodeQL didn't reach through the settings store. - routes/scriptRoutes.ts + meshtasticManager.ts: auto-responder trigger and auto-acknowledge pattern matching. - Dockerfile: add build-base + python3 to the builder stage so re2 (native) can compile from source where no prebuilt exists (Alpine/musl arm). Builder stage only — not in the runtime image. Tests: new safeRegex suite asserts linear-time behaviour on the classic (a+)+$ ReDoS pattern and rejection of backreference/lookaround. Full suite green. The two non-regex alerts are handled separately: #152 (frontend routing, not a security gate) dismissed as false-positive; #156 (authenticated admin script import, path-sanitized) dismissed as by-design. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude finished @Yeraze's task —— View job PR Review: fix(security): RE2 for user-supplied regexes
|
…cs (#3544) Claude review feedback on the RE2 security PR: 1. autoAckRegex.ts:69 — convert the MeshCore auto-ack pattern compile to compileUserRegex (the charset allowlist/length/shape guards stay as a fast pre-rejection). Residual ReDoS surface CodeQL may not flag through the barrier, now closed for consistency. 2. settingsRoutes.ts:215 — convert the regex-validation compile to compileUserRegex so stored patterns are guaranteed RE2-compatible. 3. safeRegex.ts — document that the result is not `instanceof RegExp` and that length bounding stays the caller's responsibility; add a test asserting `.source`/`.flags` behave. 4. safeRegex.test.ts — raise the ReDoS timing threshold to 1000ms and use a larger input, so the assertion can't flake on loaded CI runners. 5. Dockerfile — clarify the builder comment (build-base is the new compiler; python3 is node-gyp's other requirement). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for the thorough review — addressed in
Note: the prior CI run had two transient failures unrelated to this change — Test Suite (24.x) hit a vitest worker-teardown race ( |
|
Claude finished @Yeraze's task —— View job PR Review: fix(security): RE2 for user-supplied regexesTodo List:
Review of Updated ChangesAll five items from the previous review have been addressed. This is a clean, well-scoped security fix ready to merge. A few minor observations on the current state: What Was Addressed#1 #2 #3 #4 ReDoS timing test — Threshold raised to 1000ms at #5 Dockerfile comment — Comment at line 10 now clearly distinguishes Minor Observations (non-blocking)
SummaryThe core fix is correct and comprehensive. All user-regex execution paths — validation and runtime matching — now go through RE2. The documentation, test coverage, and Dockerfile are all in good shape. The remaining Verdict: Approved — no blocking issues remain. |

Summary
Reviews and resolves the four open CodeQL code-scanning alerts. Three are intentional features gated behind
requirePermission('settings','write'); one is a frontend false positive. None were reachable by an unauthenticated user.js/regex-injection(name-filter)js/regex-injection(auto-responder)js/user-controlled-bypass(App.tsx)js/http-to-file-access(script import)The fix (#153, #155)
Compile all user/admin-supplied regexes with RE2, a linear-time engine immune to catastrophic backtracking (ReDoS). The prior heuristic guards (length caps + nested-quantifier checks) reduced but couldn't eliminate the risk, and CodeQL correctly kept flagging the
user → RegExpdataflow. CodeQL recognizes RE2 as a safe sink, so these alerts close on the next scan.src/utils/safeRegex.ts—compileUserRegex(pattern, flags)wraps RE2 and returns aRegExp-compatible matcher (test/exec/match/replace). RE2 rejects backreferences/lookaround (the constructs that enable ReDoS) — the intended trade-off; callers keep their existing try/catch.server.ts— name-filter validation (2 sites).services/database.ts— the name-filter execution sites that actually match node names (traceroute + localstats union filters). These are the real ReDoS surface; CodeQL flagged only the validation because the taint flow is broken by the settings store.routes/scriptRoutes.ts+meshtasticManager.ts— auto-responder trigger and auto-acknowledge matching.build-base python3to the builder stage so the nativere2compiles from source where no prebuilt binary exists (Alpine/musl arm). Builder-only; not in the runtime image.Dismissals (already applied via the code-scanning API, with justifications)
if (sourceType==='meshcore' && sourceId)is frontend routing (which endpoint to call), not a security gate. Authorization is server-side;publicKeyis validated^[0-9a-f]{64}$. → false positive.Testing
safeRegexsuite: asserts linear-time behaviour on the classic(a+)+$ReDoS pattern (<100ms vs multi-second on nativeRegExp) and rejection of backreference/lookaround.tscclean.Note on the native dependency
re2is a native module. The project already ships native deps (better-sqlite3,bcrypt), and the builder stage now carries the toolchain, so multi-arch Alpine builds compile it where prebuilts are absent. The CI Docker build + system tests exercise this.🤖 Generated with Claude Code