Two search paths pass raw user input straight into a Mongo BsonRegularExpression, so the user-supplied string is evaluated as a regex, server-side:
SpikerSoft.Business/Domain/Lessons/Queries/GetAllLessons/GetAllLessonsQueryHandler.cs:47-48 — request.SearchTerm on Title/Description. GetAllLessons is anonymous-by-omission (see #415), so this is an unauthenticated DoS lever.
SpikerSoft.EventHandlers.CodeExecution/Services/UserSubmittedCodeService.cs:336-338 — searchTerm on Code/Tags/UserNotes.
A crafted catastrophic-backtracking pattern (e.g. (a+)+$) submitted as the search term is executed by the Mongo server and can pin the shared cluster's CPU — an #411-class availability bomb — and it's a regex-injection (unexpected match semantics) besides.
The safe pattern already exists in the repo: OpsSecurityAlertQueryBuilder / OpsIncidentQueryBuilder wrap the value in Regex.Escape(...).
Fix
Introduced SpikerSoft.Data.Search.MongoRegexSearch.LiteralContains(term) — Regex.Escapes the term so it matches literally (which is the behaviour a search box should have anyway) — and routed both call sites (all 5 usages) through it. Escaping neutralizes the metacharacters that enable ReDoS.
Note: this changes search from "regex" to "literal substring" — the correct/expected behaviour for these boxes; no one is relying on regex search in a kids' lessons/code finder.
Verification
MongoRegexSearchTests (6): escapes catastrophic/metacharacter inputs to their literal form, options stay case-insensitive, null-safe. Build clean.
Resolved by spikersoft-backend PR (linked below). Filing so the fix is traceable.
## Problem
Two search paths pass **raw user input** straight into a Mongo `BsonRegularExpression`, so the user-supplied string is evaluated **as a regex, server-side**:
- `SpikerSoft.Business/Domain/Lessons/Queries/GetAllLessons/GetAllLessonsQueryHandler.cs:47-48` — `request.SearchTerm` on Title/Description. **`GetAllLessons` is anonymous-by-omission** (see #415), so this is an **unauthenticated** DoS lever.
- `SpikerSoft.EventHandlers.CodeExecution/Services/UserSubmittedCodeService.cs:336-338` — `searchTerm` on Code/Tags/UserNotes.
A crafted catastrophic-backtracking pattern (e.g. `(a+)+$`) submitted as the search term is executed by the Mongo server and can **pin the shared cluster's CPU** — an #411-class availability bomb — and it's a regex-injection (unexpected match semantics) besides.
The **safe pattern already exists** in the repo: `OpsSecurityAlertQueryBuilder` / `OpsIncidentQueryBuilder` wrap the value in `Regex.Escape(...)`.
## Fix
Introduced `SpikerSoft.Data.Search.MongoRegexSearch.LiteralContains(term)` — `Regex.Escape`s the term so it matches **literally** (which is the behaviour a search box should have anyway) — and routed both call sites (all 5 usages) through it. Escaping neutralizes the metacharacters that enable ReDoS.
Note: this changes search from "regex" to "literal substring" — the correct/expected behaviour for these boxes; no one is relying on regex search in a kids' lessons/code finder.
## Verification
`MongoRegexSearchTests` (6): escapes catastrophic/metacharacter inputs to their literal form, options stay case-insensitive, null-safe. Build clean.
Resolved by spikersoft-backend PR (linked below). Filing so the fix is traceable.
Resolved in spikersoft-backend PR #126 (merged to master as b5bb73d). MongoRegexSearch.LiteralContains now Regex.Escapes user search input at all 5 sites (GetAllLessons + UserSubmittedCode); ReDoS/regex-injection closed, incl. the anonymous lesson-search path. 6/6 tests. Closing.
Resolved in spikersoft-backend PR #126 (merged to `master` as `b5bb73d`). `MongoRegexSearch.LiteralContains` now `Regex.Escape`s user search input at all 5 sites (GetAllLessons + UserSubmittedCode); ReDoS/regex-injection closed, incl. the anonymous lesson-search path. 6/6 tests. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
Two search paths pass raw user input straight into a Mongo
BsonRegularExpression, so the user-supplied string is evaluated as a regex, server-side:SpikerSoft.Business/Domain/Lessons/Queries/GetAllLessons/GetAllLessonsQueryHandler.cs:47-48—request.SearchTermon Title/Description.GetAllLessonsis anonymous-by-omission (see #415), so this is an unauthenticated DoS lever.SpikerSoft.EventHandlers.CodeExecution/Services/UserSubmittedCodeService.cs:336-338—searchTermon Code/Tags/UserNotes.A crafted catastrophic-backtracking pattern (e.g.
(a+)+$) submitted as the search term is executed by the Mongo server and can pin the shared cluster's CPU — an #411-class availability bomb — and it's a regex-injection (unexpected match semantics) besides.The safe pattern already exists in the repo:
OpsSecurityAlertQueryBuilder/OpsIncidentQueryBuilderwrap the value inRegex.Escape(...).Fix
Introduced
SpikerSoft.Data.Search.MongoRegexSearch.LiteralContains(term)—Regex.Escapes the term so it matches literally (which is the behaviour a search box should have anyway) — and routed both call sites (all 5 usages) through it. Escaping neutralizes the metacharacters that enable ReDoS.Note: this changes search from "regex" to "literal substring" — the correct/expected behaviour for these boxes; no one is relying on regex search in a kids' lessons/code finder.
Verification
MongoRegexSearchTests(6): escapes catastrophic/metacharacter inputs to their literal form, options stay case-insensitive, null-safe. Build clean.Resolved by spikersoft-backend PR (linked below). Filing so the fix is traceable.
Resolved in spikersoft-backend PR #126 (merged to
masterasb5bb73d).MongoRegexSearch.LiteralContainsnowRegex.Escapes user search input at all 5 sites (GetAllLessons + UserSubmittedCode); ReDoS/regex-injection closed, incl. the anonymous lesson-search path. 6/6 tests. Closing.