Skip to content

fix: prevent DoS on search endpoint via query length limit and input validation#1954

Open
fennhelloworld wants to merge 2 commits into
SecureBananaLabs:mainfrom
fennhelloworld:fix/search-dos-prevention-1781
Open

fix: prevent DoS on search endpoint via query length limit and input validation#1954
fennhelloworld wants to merge 2 commits into
SecureBananaLabs:mainfrom
fennhelloworld:fix/search-dos-prevention-1781

Conversation

@fennhelloworld
Copy link
Copy Markdown

Fix for #1781: Prevent DoS on Search Endpoint

Vulnerability

The GET /api/search endpoint had no input validation or query length limit, allowing DoS attacks:

  1. Memory exhaustion: An attacker could send arbitrarily long query strings (megabytes). The existing .slice(0, 200) silently truncated the output but still required Express to parse and allocate memory for the entire string.
  2. ReDoS (Regular Expression Denial of Service): The search query accepted regex metacharacters (\, *, +, {, }, (, ), [, ], |, ^, $). If the search service later implements regex-based matching, these could trigger catastrophic backtracking.
  3. No endpoint-specific rate limiting: Only a global API limiter (200 req/15min) protected the endpoint — insufficient for a resource-intensive search operation.

Changes

File Change
validators/search.js New — Zod schema enforcing max 200 chars and safe-characters-only regex; sanitizeSearchQuery() defense-in-depth function
middleware/validate.js New — Generic validateQuery() middleware for Zod schema validation on query params
middleware/searchRateLimit.js New — Dedicated search rate limiter: 20 req/min per IP (stricter than the global 200/15min)
routes/searchRoutes.js Updated to use searchLimitervalidateQuerysearch middleware chain; factory pattern for fresh limiter instances
controllers/searchController.js Replaced silent .slice() truncation with sanitizeSearchQuery() (defense-in-depth after validation)
app.js Updated to use createSearchRoutes() factory
tests/search.test.js New — 7 tests covering: valid queries, empty queries, length rejection, ReDoS char rejection, allowed punctuation, sanitization, and rate limiting

Test Results

✓ GET /api/search with valid query returns 200
✓ GET /api/search without q param returns 200 with empty query
✓ GET /api/search rejects query longer than 200 characters
✓ GET /api/search rejects query with regex special characters
✓ GET /api/search accepts query with allowed punctuation
✓ sanitizeSearchQuery strips dangerous regex characters
✓ search endpoint rate limits after 20 requests

Defense Layers

  1. Zod schema validation (middleware) — rejects queries >200 chars and disallowed chars with 400
  2. Sanitization (controller) — strips any regex metacharacters as defense-in-depth
  3. Rate limiting — 20 req/min per IP prevents brute-force search abuse
  4. Global API limiter — 200 req/15min still applies as outer layer

Fixes #1781

tianfengguo added 2 commits May 30, 2026 11:15
- Add admin role middleware (SecureBananaLabs#1770): admin routes now require admin role
- Add auth to upload routes (SecureBananaLabs#1771): unauthenticated uploads blocked
- Add auth to payment routes (SecureBananaLabs#1772): unauthenticated payments blocked
- Add user input validation (SecureBananaLabs#1773): Zod schema for user creation
- Configure CORS origin from env (SecureBananaLabs#1774): no longer wide open
- Add auth to job creation (SecureBananaLabs#1776): unauthenticated job posts blocked
- Add search query length limit (SecureBananaLabs#1777): prevent long query DoS
…validation (SecureBananaLabs#1781)

- Add Zod-based query validation (max 200 chars, safe chars only)
- Reject regex metacharacters (\*+{}()[]|^$) that enable ReDoS
- Add dedicated search rate limiter (20 req/min per IP)
- Add generic validateQuery middleware for reuse
- Add defense-in-depth sanitizeSearchQuery function
- Add comprehensive test suite (7 tests)

Vulnerability: The search endpoint previously had no input validation.
An attacker could send arbitrarily long query strings to exhaust server
memory, or inject regex metacharacters that could cause catastrophic
backtracking (ReDoS) when the search service implements regex-based
matching. The silent .slice() truncation still required the full string
to be parsed by Express.

Fixes SecureBananaLabs#1781
github-actions Bot added a commit that referenced this pull request May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: prevent DoS on search endpoint via query length limit and input validation

1 participant