#18933: fix(security): use timingSafeEqual for pairing code comparison
size: S
## Summary
Replace direct string comparison of pairing codes with `crypto.timingSafeEqual` to prevent timing side-channel attacks.
## Problem
The pairing code lookup in `approveChannelPairingCode` uses `===` for comparison:
```ts
String(r.code ?? '').toUpperCase() !== code
```
This is vulnerable to timing attacks — an attacker on the same network could measure response time differences to brute-force valid pairing codes during the approval window.
## Fix
Zero-pad both buffers to `Math.max(a.length, b.length)` before calling `crypto.timingSafeEqual`, so:
1. Length-mismatched inputs **never short-circuit** before the constant-time comparison (no length-leak)
2. `timingSafeEqual` is **always called** regardless of input length
3. No HMAC overhead — avoids the entropy concerns raised in #19864
This approach was suggested by @arosstale in the #19864 review thread as the simplest correct fix.
## Changes
- `src/pairing/pairing-store.ts` — zero-pad both buffers before `timingSafeEqual` in `approveChannelPairingCode`
- `src/pairing/pairing-store.test.ts` — added spy assertion to confirm `timingSafeEqual` is called even for different-length inputs
## Relationship to #19864
That PR addressed `safeEqualSecret` (gateway auth tokens). This PR addresses the separate `approveChannelPairingCode` function, which does not use `safeEqualSecret`. Both functions had the same class of vulnerability.
Most Similar PRs
#8779: fix(security): use constant-time comparison for token validation
by hleliofficiel · 2026-02-04
73.4%
#16773: fix(security): OC-100 add rate limiting to pairing code verification
by aether-ai-agent · 2026-02-15
69.0%
#23692: fix(pairing): add brute-force protection for DM pairing codes
by widingmarcus-cyber · 2026-02-22
68.3%
#16898: Fix Zalo webhook secret comparison vulnerable to timing attacks
by Clawborn · 2026-02-15
64.7%
#17425: fix(gateway): auto-approve scope/role upgrades for already-paired d...
by sauerdaniel · 2026-02-15
63.6%
#22636: fix(whatsapp): skip pairing store merge when dmPolicy is allowlist (#…
by anillBhoi · 2026-02-21
63.0%
#13090: fix: Device-pair extension leaks gateway credentials in chat messages
by coygeek · 2026-02-10
62.5%
#23690: fix(gateway): subagent sessions fail with pairing required on loopb...
by yinghaosang · 2026-02-22
61.8%
#17900: refactor(security): extract shared normalizeAllowFromList into audi...
by iyoda · 2026-02-16
61.3%
#22381: Security/Gateway: block cross-origin silent auto-pairing in auth mo...
by bmendonca3 · 2026-02-21
61.3%