Fix security vulnerabilities and logic flaws

This commit is contained in:
Timo
2026-04-22 10:04:46 +02:00
parent bf48d6a75d
commit d750d96db5
4 changed files with 82 additions and 27 deletions
+31 -6
View File
@@ -11,11 +11,28 @@ let currentTabId = null;
let currentTabTitle = null; // New: for Smart Matching
let logs = [];
let history = []; // New: for Action History
let storageInitialized = false;
let pendingLogs = [];
let pendingHistory = [];
// Restore state from session storage
chrome.storage.session.get(['logs', 'history'], (data) => {
if (data.logs) logs = data.logs;
if (data.history) history = data.history;
storageInitialized = true;
if (pendingLogs.length > 0) {
logs.unshift(...pendingLogs);
if (logs.length > 50) logs = logs.slice(0, 50);
chrome.storage.session.set({ logs });
pendingLogs = [];
}
if (pendingHistory.length > 0) {
history.unshift(...pendingHistory);
if (history.length > 20) history = history.slice(0, 20);
chrome.storage.session.set({ history });
pendingHistory = [];
}
});
let reconnectTimer = null;
@@ -56,9 +73,13 @@ function addLog(message, type = 'info') {
message,
type
};
logs.unshift(log);
if (logs.length > 50) logs.pop();
chrome.storage.session.set({ logs });
if (!storageInitialized) {
pendingLogs.unshift(log);
} else {
logs.unshift(log);
if (logs.length > 50) logs.pop();
chrome.storage.session.set({ logs });
}
chrome.runtime.sendMessage({ type: 'LOG_UPDATE', log }).catch(() => {});
}
@@ -260,9 +281,13 @@ function addToHistory(action, senderId) {
senderId: senderId || 'You',
timestamp: new Date().toISOString()
};
history.unshift(historyEntry);
if (history.length > 20) history.pop();
chrome.storage.session.set({ history });
if (!storageInitialized) {
pendingHistory.unshift(historyEntry);
} else {
history.unshift(historyEntry);
if (history.length > 20) history.pop();
chrome.storage.session.set({ history });
}
chrome.runtime.sendMessage({ type: 'HISTORY_UPDATE', history }).catch(() => {});
}
+27 -15
View File
@@ -7,7 +7,7 @@
if (window.koalaSyncInjected) return;
window.koalaSyncInjected = true;
let isProcessingCommand = false;
let processingCommandUntil = 0;
// --- Helper: find the best video element on the page ---
function findVideo() {
@@ -20,7 +20,7 @@
const video = findVideo();
if (!video) return;
isProcessingCommand = true;
processingCommandUntil = Date.now() + 1000;
try {
const host = window.location.hostname.toLowerCase();
const isYouTube = host.includes('youtube.com');
@@ -60,9 +60,6 @@
}
} catch (e) {
console.error('KoalaSync Media Action Error:', e);
} finally {
// Guarantee reset even on early returns in YouTube/Twitch blocks
setTimeout(() => { isProcessingCommand = false; }, 1000);
}
}
@@ -91,6 +88,12 @@
// Listen for commands from background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'get_current_time') {
const video = findVideo();
sendResponse({ currentTime: video ? video.currentTime : undefined });
return true;
}
if (message.type === 'SERVER_COMMAND') {
const { action, payload } = message;
@@ -101,17 +104,17 @@
} else if (action === 'seek') {
tryMediaAction('seek', payload);
} else if (action === 'force_sync_prepare') {
isProcessingCommand = true;
processingCommandUntil = Date.now() + 10000;
const video = findVideo();
if (video) {
video.pause();
video.currentTime = payload.targetTime;
pollSeekReady(payload.targetTime).then(() => {
chrome.runtime.sendMessage({ type: 'FORCE_SYNC_ACK' });
setTimeout(() => { isProcessingCommand = false; }, 1000);
processingCommandUntil = Date.now() + 1000;
});
} else {
isProcessingCommand = false;
processingCommandUntil = 0;
}
} else if (action === 'force_sync_execute') {
tryMediaAction('play');
@@ -121,7 +124,7 @@
// Detect native events
function reportEvent(action) {
if (isProcessingCommand) return;
if (Date.now() < processingCommandUntil) return;
const video = findVideo();
if (!video) return;
@@ -147,15 +150,24 @@
// SPA Navigation Handler (MutationObserver)
let lastMutate = 0;
let observerTimeout = null;
function checkVideo() {
lastMutate = Date.now();
const video = findVideo();
if (video && !video.dataset.koalaAttached) {
console.log('KoalaSync: New video detected via navigation.');
setupListeners();
}
}
const observer = new MutationObserver(() => {
const now = Date.now();
if (now - lastMutate >= 1000) {
lastMutate = now;
const video = findVideo();
if (video && !video.dataset.koalaAttached) {
console.log('KoalaSync: New video detected via navigation.');
setupListeners();
}
checkVideo();
} else {
if (observerTimeout) clearTimeout(observerTimeout);
observerTimeout = setTimeout(checkVideo, 1000 - (now - lastMutate));
}
});
observer.observe(document.body, { childList: true, subtree: true });
+9 -6
View File
@@ -337,12 +337,15 @@ function showError(msg) {
elements.password.style.borderColor = 'var(--error)';
// Shake effect
document.getElementById('tab-room').animate([
{ transform: 'translateX(0)' },
{ transform: 'translateX(-5px)' },
{ transform: 'translateX(5px)' },
{ transform: 'translateX(0)' }
], { duration: 200, iterations: 2 });
const activeTab = document.querySelector('.tab-content.active');
if (activeTab) {
activeTab.animate([
{ transform: 'translateX(0)' },
{ transform: 'translateX(-5px)' },
{ transform: 'translateX(5px)' },
{ transform: 'translateX(0)' }
], { duration: 200, iterations: 2 });
}
setTimeout(() => {
if (elements.roomError) elements.roomError.style.display = 'none';
+15
View File
@@ -84,6 +84,16 @@ setInterval(() => {
const eventCounts = new Map(); // socketId -> { count, resetTime }
// Clean up connection counts to prevent memory leak
setInterval(() => {
const now = Date.now();
for (const [ip, entry] of connectionCounts.entries()) {
if (now > entry.resetTime) {
connectionCounts.delete(ip);
}
}
}, 60000);
function checkConnectionRate(ip) {
const now = Date.now();
const entry = connectionCounts.get(ip) || { count: 0, resetTime: now + 60000 };
@@ -150,6 +160,9 @@ io.on('connection', (socket) => {
// Cleanup old room if re-joining
const oldMapping = socketToRoom.get(socket.id);
if (oldMapping && oldMapping.roomId === roomId) {
return; // Already in this room, ignore to prevent spam
}
if (oldMapping && oldMapping.roomId !== roomId) {
socket.leave(oldMapping.roomId);
const oldRoom = rooms.get(oldMapping.roomId);
@@ -232,6 +245,8 @@ io.on('connection', (socket) => {
return;
}
if (!data || typeof data !== 'object') return; // Prevent null/invalid payload crash
const mapping = socketToRoom.get(socket.id);
if (mapping) {
const room = rooms.get(mapping.roomId);