Files
2026-05-29 09:03:47 -04:00

2.9 KiB
Raw Permalink Blame History

Phase: 8 Sequence: 004 Slug: rate-limit-substring-bypass Verdict: VALID Rationale: Rate limiting sensitive path detection uses substring matching (path.includes) with incomplete sensitive list; sensitive operations like darkwatch.runScan and voiceprint.analyzeAudio get standard tier (100/min) instead of stricter limits Severity-Original: medium Severity: medium PoC-Status: pending Pre-FP-Flag: none Debate: piolium/attack-surface/balanced-chamber-summary.md

Summary

The rate limiting middleware in web/src/server/api/utils.ts detects sensitive paths using path.includes(p) where p is from a hardcoded list of sensitive operation names (["login", "signup", "forgotPassword", "resetPassword"]). This substring matching is imprecise and the sensitive list is incomplete — it only covers auth-related operations. Sensitive operations like darkwatch.runScan (triggers expensive external API calls), voiceprint.analyzeAudio (processes audio through ML), and spamshield.classifySMS get the standard authenticated tier (100/min) instead of a stricter sensitive tier (3/hr).

Location

  • web/src/server/api/utils.ts lines 3538 (rate limiting middleware)

Attacker Control

Any authenticated user can call sensitive operations at the higher rate limit (100/min) since they are not in the sensitive path list. The attacker does not need to craft special procedure paths — they simply use normal operations that are not covered by the sensitive list.

Trust Boundary Crossed

Rate limiting policy boundary. The rate limiter applies different limits based on operation sensitivity, and the incomplete sensitive list allows operations that should be rate-limited to proceed at higher rates.

Impact

Resource exhaustion and cost abuse for sensitive operations:

  • darkwatch.runScan can be called 100 times/min instead of 3/hr, triggering expensive external API calls (HIBP, SecurityTrails, Censys, Shodan)
  • voiceprint.analyzeAudio can be called 100 times/min, consuming memory and CPU for ML processing
  • Service disruption for other users on the same server

Evidence

const sensitivePaths = ["login", "signup", "forgotPassword", "resetPassword"];
const effectiveTier = sensitivePaths.some((p) => path.includes(p)) ? "sensitive" : tier;

Reproduction Steps

  1. Authenticated user calls darkwatch.runScan with a watchlist item
  2. The procedure path "darkwatch.runScan" does not contain any sensitive path substring
  3. Rate limiter assigns authenticated tier (100/min) instead of sensitive tier (3/hr)
  4. User can trigger 100 scans per minute, each triggering 5+ external API calls
  5. Cumulative cost and resource impact affects all users

Defense Search Results

  • path.includes(p) substring matching is imprecise
  • Sensitive list only covers auth-related operations
  • rateLimitedProcedure middleware is not applied to all procedures
  • No default sensitive tier for write operations (mutations)
  • No IP-based rate limiting as secondary dimension