Security [MEDIUM]: Blueprint validator uses native RegExp — admin-set pattern enables ReDoS #52

Closed
opened 2026-04-16 22:05:11 +02:00 by Hartmut · 1 comment
Owner

Problem

packages/engine/src/blueprint/validator.ts:98 does new RegExp(v.pattern).test(strVal) where pattern comes from admin-editable BlueprintField. A catastrophic-backtracking pattern (^(a+)+$) plus crafted input freezes the event loop. Relevant if MANAGE_BLUEPRINTS is ever delegated or if an admin-account is compromised.

Evidence

  • packages/engine/src/blueprint/validator.ts:98 — new RegExp(v.pattern).test(strVal)

Impact

DoS: single request to create/update resource with crafted value + malicious pattern → full process freeze for multiple seconds per request.

Proposed Fix

Replace RegExp with re2 (linear-time regex). Also reject unsafe patterns at blueprint save-time via safe-regex. Fallback: wrap test in setTimeout-cancel pattern with Worker.

Acceptance Criteria

  • re2 or safe-regex integrated
  • Unit test: ReDoS pattern completes in < 50 ms
  • Blueprint save rejects unsafe patterns

Parent Epic: #1
Source: Full-Codebase Security Audit 2026-04-16 (B-8)

## Problem `packages/engine/src/blueprint/validator.ts:98` does `new RegExp(v.pattern).test(strVal)` where pattern comes from admin-editable BlueprintField. A catastrophic-backtracking pattern (`^(a+)+$`) plus crafted input freezes the event loop. Relevant if MANAGE_BLUEPRINTS is ever delegated or if an admin-account is compromised. ## Evidence - `packages/engine/src/blueprint/validator.ts:98 — new RegExp(v.pattern).test(strVal)` ## Impact DoS: single request to create/update resource with crafted value + malicious pattern → full process freeze for multiple seconds per request. ## Proposed Fix Replace `RegExp` with `re2` (linear-time regex). Also reject unsafe patterns at blueprint save-time via `safe-regex`. Fallback: wrap test in `setTimeout`-cancel pattern with Worker. ## Acceptance Criteria - [ ] re2 or safe-regex integrated - [ ] Unit test: ReDoS pattern completes in < 50 ms - [ ] Blueprint save rejects unsafe patterns --- Parent Epic: #1 Source: Full-Codebase Security Audit 2026-04-16 (B-8)
Hartmut added the security label 2026-04-16 22:05:11 +02:00
Author
Owner

Resolved in commit 019702c (security: ReDoS hardening on blueprint field validator).

Three-layer defence:

  1. Save-time (packages/shared/src/schemas/blueprint.schema.ts:33-54)FieldValidationSchema.pattern now has .max(200) and a .refine() that rejects grouped nested-quantifier shapes ((x+)+, (?:x*)+, (x{n,})* …). Admin UI will show a clear validation error at blueprint save time instead of silently storing the ReDoS pattern.

  2. Runtime (packages/engine/src/blueprint/validator.ts:26-33, 142-171)

    • isSuspectRegexPattern() re-runs the same heuristic before invoking new RegExp(). If it fires, the field fails validation OUTRIGHT; the regex is never compiled or run.
    • Input strings are sliced to 4096 chars before .test() (belt-and-suspenders) so even a benign pattern against a 10 MB payload returns in < 50 ms.
    • new RegExp() compile failures are caught → validation error instead of 500.
  3. Testspackages/engine/src/__tests__/blueprint-validator-redos.test.ts (10 cases) pins all three behaviours:

    • ^(a+)+$ + 30-'a' attack input → errors in < 50 ms
    • All canonical nested-quantifier shapes flagged
    • Safe patterns (^[a-z]+$, ^\d{3}-\d{4}$, email-style) pass through
    • Huge (12 kB) benign input still validates in < 50 ms

Acceptance-criteria:

  • Safe-regex heuristic integrated (in-house, avoided re2 native-module install cost)
  • Unit test: ReDoS pattern completes in < 50 ms
  • Blueprint save rejects unsafe patterns

Closing.

Resolved in commit 019702c (`security: ReDoS hardening on blueprint field validator`). **Three-layer defence:** 1. **Save-time (`packages/shared/src/schemas/blueprint.schema.ts:33-54`)** — `FieldValidationSchema.pattern` now has `.max(200)` and a `.refine()` that rejects grouped nested-quantifier shapes (`(x+)+`, `(?:x*)+`, `(x{n,})*` …). Admin UI will show a clear validation error at blueprint save time instead of silently storing the ReDoS pattern. 2. **Runtime (`packages/engine/src/blueprint/validator.ts:26-33, 142-171`)** — - `isSuspectRegexPattern()` re-runs the same heuristic before invoking `new RegExp()`. If it fires, the field fails validation OUTRIGHT; the regex is never compiled or run. - Input strings are sliced to 4096 chars before `.test()` (belt-and-suspenders) so even a benign pattern against a 10 MB payload returns in < 50 ms. - `new RegExp()` compile failures are caught → validation error instead of 500. 3. **Tests** — `packages/engine/src/__tests__/blueprint-validator-redos.test.ts` (10 cases) pins all three behaviours: - `^(a+)+$` + 30-'a' attack input → errors in < 50 ms - All canonical nested-quantifier shapes flagged - Safe patterns (`^[a-z]+$`, `^\d{3}-\d{4}$`, email-style) pass through - Huge (12 kB) benign input still validates in < 50 ms Acceptance-criteria: - [x] Safe-regex heuristic integrated (in-house, avoided re2 native-module install cost) - [x] Unit test: ReDoS pattern completes in < 50 ms - [x] Blueprint save rejects unsafe patterns Closing.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Hartmut/CapaKraken#52