diff --git a/CHANGELOG.md b/CHANGELOG.md index 358d8a2..2682493 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to the KoalaSync browser extension and relay server. --- +## [v2.0.6] — 2026-06-03 + +### Performance & Security Hardening +- Optimized failed authentication attempts cache eviction algorithm to $O(1)$ by exploiting Javascript `Map` insertion-order properties. This completely removes the previous array copying and sorting bottleneck, neutralizing a potential main-thread blocking DoS vector under heavy brute-force password traffic. + +--- + ## [v2.0.5] — 2026-06-03 ### Security & Hardening diff --git a/README.md b/README.md index b7bca14..a9f5e2f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Chrome Extension

-

New v2.0.5 Release! — See what's changed

+

New v2.0.6 Release! — See what's changed

KoalaSync is a lightweight Browser Extension and Relay Server for synchronized video playback on almost any website with a video element—YouTube, Twitch, Netflix, Emby, Jellyfin, and beyond. Built with a focus on Data Sovereignty and Performance.

diff --git a/server/index.js b/server/index.js index 8f22450..6c2f7e0 100644 --- a/server/index.js +++ b/server/index.js @@ -149,17 +149,19 @@ function recordAuthFailure(ip, roomId) { for (const [key, record] of failedAuthAttempts.entries()) { if (now - record.lastAttempt > 15 * 60 * 1000) { failedAuthAttempts.delete(key); + } else { + break; // Since entries are insertion-ordered by time, all subsequent entries are newer } } - // 2. If still over 50k, perform LRU-style eviction on the oldest 10,000 entries + // 2. If still over 50k, perform LRU-style eviction on the oldest 10,000 entries (first items in Map order) if (failedAuthAttempts.size > 50000) { - log('SECURITY', 'failedAuthAttempts size exceeded 50000. Performing LRU-style eviction.'); - const sortedEntries = Array.from(failedAuthAttempts.entries()) - .sort((a, b) => a[1].lastAttempt - b[1].lastAttempt); - - for (let i = 0; i < 10000 && i < sortedEntries.length; i++) { - failedAuthAttempts.delete(sortedEntries[i][0]); + log('SECURITY', 'failedAuthAttempts size exceeded 50000. Performing insertion-order eviction.'); + for (const [key] of failedAuthAttempts.entries()) { + if (failedAuthAttempts.size <= 40000) { + break; + } + failedAuthAttempts.delete(key); } } } @@ -167,6 +169,7 @@ function recordAuthFailure(ip, roomId) { const record = failedAuthAttempts.get(key) || { count: 0, lastAttempt: 0 }; record.count++; record.lastAttempt = Date.now(); + failedAuthAttempts.delete(key); // Remove first to update insertion order (moves key to the end of iteration) failedAuthAttempts.set(key, record); } diff --git a/website/www/version.json b/website/www/version.json index b1053ac..c07cc8e 100644 --- a/website/www/version.json +++ b/website/www/version.json @@ -1,4 +1,4 @@ { "version": "2.0.5", - "date": "2026-06-03T09:32:00Z" + "date": "2026-06-03T09:34:22Z" }