Files
Kordant/tasks/security-fixes/04-fix-rate-limit-substring-bypass.md
2026-05-29 09:03:47 -04:00

2.7 KiB

04. Fix rate limit bypass via incomplete sensitive path list

meta: id: security-fixes-04 feature: security-fixes priority: P1 depends_on: [] tags: [implementation, tests-required, medium-severity]

objective:

  • Prevent resource exhaustion by replacing substring-based rate limiting with exact procedure name matching and a complete sensitive operation list

deliverables:

  • Updated rate limiter in web/src/server/api/utils.ts using exact procedure name matching
  • Expanded sensitive procedure list covering darkwatch, voiceprint, and other expensive operations
  • Unit tests for rate limit matching logic

steps:

  1. Examine the rate limiter at web/src/server/api/utils.ts:35-38 (substring matching on sensitivePaths)
  2. Review the tRPC router definitions to identify all expensive procedures:
    • darkwatch.runScan (external API calls: HIBP, SecurityTrails, Censys, Shodan)
    • voiceprint.analyzeAudio (300MB+ memory per request)
    • Any other CPU/memory/network-intensive procedures
  3. Replace sensitivePaths.some(p => path.includes(p)) with exact procedure name matching using a Set of full procedure paths (e.g., darkwatch.runScan)
  4. Define appropriate rate limits per procedure category:
    • Auth operations: 3/hr (existing)
    • Darkwatch scans: 5/hr (expensive external API calls)
    • VoicePrint analysis: 10/hr (high memory usage)
    • Default protected: 100/min (existing)
  5. Update protectedProcedure configuration at web/src/server/api/utils.ts:23-28 if needed

tests:

  • Unit: Exact procedure name matching correctly identifies darkwatch.runScan as sensitive
  • Unit: Substring attacks like darkwatch.runScanLike do not trigger sensitive tier
  • Unit: voiceprint.analyzeAudio is classified as sensitive
  • Unit: Auth procedures (login, signup) still match the sensitive tier
  • Integration: Rapid fire requests to darkwatch.runScan are rate-limited at the sensitive tier

acceptance_criteria:

  • Rate limiter uses exact procedure name matching (not substring)
  • All expensive procedures are in the sensitive operation list
  • Different sensitive procedures can have different rate limits
  • Existing rate limits for auth operations are preserved
  • No false positives from substring matching

validation:

  • cd web && bun test — all tests pass
  • Send rapid requests to darkwatch.runScan and verify rate limiting kicks in at the sensitive tier
  • Verify darkwatch.runScanLike (non-existent) does not trigger sensitive tier

notes:

  • Finding p8-004: The current substring heuristic (path.includes(p)) is too broad and incomplete
  • Consider a tiered approach: sensitive (3/hr), expensive (10/hr), standard (100/min)
  • Review all router definitions to ensure no new expensive procedures are missed