← Back to PRs

#16773: fix(security): OC-100 add rate limiting to pairing code verification

by aether-ai-agent open 2026-02-15 03:30 View on GitHub →
stale size: S trusted-contributor
## Summary - Add in-memory rate limiter to `approveChannelPairingCode` to block brute-force pairing code attempts - Lock out channel after 10 failed attempts within a 15-minute sliding window - Reset rate limit counter on successful pairing approval - Throw descriptive error (`"Too many failed pairing attempts. Try again later."`) when rate-limited - Add 4 comprehensive test cases for rate limiting behavior ## Security Impact **OC-100 Medium (CWE-307, Improper Restriction of Excessive Authentication Attempts)** — Attack vectors: 1. **Brute-force pairing codes**: `approveChannelPairingCode` accepted unlimited attempts with no failed-attempt tracking, no lockout, and no rate limiting. An attacker could automate thousands of code guesses per second against the 8-character pairing code space (31^8 ≈ 852B combinations), significantly reducing the effective security of the pairing mechanism. 2. **Automated enumeration**: Without rate limiting, automated scripts could systematically try every possible code within the 1-hour TTL window. ## Changes | File | Change | |------|--------| | `src/pairing/pairing-store.ts` | Add rate limit constants (`PAIRING_MAX_FAILED_ATTEMPTS=10`, `PAIRING_RATE_LIMIT_WINDOW_MS=15min`), in-memory `Map<string, RateLimitEntry>` tracker, `isPairingRateLimited()`, `recordFailedPairingAttempt()`, `resetPairingRateLimit()` helpers, and rate limit check in `approveChannelPairingCode` | | `src/pairing/pairing-store.test.ts` | Add `"pairing code rate limiting (OC-100)"` test suite with 4 cases: below-threshold allows, lockout after 10 failures, reset on success, per-channel isolation | ## Test plan - [x] TypeScript compiles with zero errors (`tsc --noEmit`) - [x] All 8 tests pass (4 existing + 4 new rate limiting tests) - [x] Linter passes with 0 warnings and 0 errors (`oxlint --type-aware`) - [x] Below-threshold attempts (9 failures) return `null` without throwing - [x] 11th failed attempt throws `"Too many failed pairing attempts"` - [x] Successful pairing resets the counter, allowing new attempts - [x] Rate limits are isolated per channel (discord lockout doesn't affect signal) --- *Created by [Aether AI Agent](https://tryaether.ai) — AI security research and remediation agent.* <!-- greptile_comment --> <h3>Greptile Summary</h3> Added in-memory rate limiting to pairing code verification to prevent brute-force attacks on 8-character pairing codes. The implementation uses a 15-minute sliding window with a 10-attempt limit per channel. The race condition identified in previous review has been fixed by moving the rate limit check inside the file lock (commit `05dd15ba`). Tests thoroughly cover the rate limiting behavior including threshold enforcement, reset on success, and per-channel isolation. <h3>Confidence Score: 4/5</h3> - Safe to merge with minor operational consideration about in-memory state - The implementation correctly addresses CWE-307 with proper rate limiting inside the file lock to prevent race conditions. Tests are comprehensive. The only consideration is that rate limit state is lost on restart (by design for operational flexibility), which is acceptable for this use case. - No files require special attention <sub>Last reviewed commit: 05dd15b</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs