Priority: Medium
Description
RelayerAuth (relayer-auth.ts) gates the WebSocket relayer used by the ZK state syncer. Key validation at relayer-auth.ts:47 is this.apiKeys.has(key) — a standard Set<string> lookup, which relies on JS string equality that is not defined to run in constant time and typically short-circuits on the first mismatched byte. No crypto.timingSafeEqual or equivalent constant-time comparison is used anywhere in the auth path.
Failure scenario
A remote attacker with many connection attempts and precise timing measurement can incrementally recover a valid API key character-by-character via a classic timing attack against the string/Set equality check, since comparisons bail out early on the first mismatch. This is exploitable on a network-facing auth boundary.
Suggested fix
Compare candidate keys against the known set using a constant-time comparison (e.g. crypto.timingSafeEqual on fixed-length buffers, or a constant-time comparison against a fixed-size HMAC of each candidate) instead of Set.has()/===.
Priority: Medium
Description
RelayerAuth(relayer-auth.ts) gates the WebSocket relayer used by the ZK state syncer. Key validation atrelayer-auth.ts:47isthis.apiKeys.has(key)— a standardSet<string>lookup, which relies on JS string equality that is not defined to run in constant time and typically short-circuits on the first mismatched byte. Nocrypto.timingSafeEqualor equivalent constant-time comparison is used anywhere in the auth path.Failure scenario
A remote attacker with many connection attempts and precise timing measurement can incrementally recover a valid API key character-by-character via a classic timing attack against the string/Set equality check, since comparisons bail out early on the first mismatch. This is exploitable on a network-facing auth boundary.
Suggested fix
Compare candidate keys against the known set using a constant-time comparison (e.g.
crypto.timingSafeEqualon fixed-length buffers, or a constant-time comparison against a fixed-size HMAC of each candidate) instead ofSet.has()/===.