// Security utility functions for caption.ninja /** * Checks if a stream ID is considered insecure based on common patterns * @param {string} streamId - The stream ID to check * @returns {boolean} - True if the stream ID is insecure, false otherwise */ function isInsecureStreamId(streamId) { // Common insecure stream IDs const insecurePatterns = [ 'test', 'demo', 'guest', 'user', 'admin', 'default', 'sample', 'example', 'temp', 'temporary', 'public', 'room', 'stream', 'live', 'broadcast', 'channel', 'password', '1234', '0000', 'abcd', 'qwerty', 'welcome', 'hello', 'anonymous', 'anon', 'visitor', 'cc', 'caption', 'captions', 'english', 'show', 'a', 'video', 'audio', 'media', 'session', 'meeting', 'class', 'lecture', 'presentation', 'webinar', 'event', 'host', 'presenter', 'speaker', 'viewer', 'audience', 'main', 'primary', 'secondary', 'backup', 'alt', 'new', 'old', 'first', 'last', 'next', 'previous', 'home', 'office', 'work', 'personal', 'private', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'weekend', 'weekday', 'today', 'morning', 'afternoon', 'evening', 'night', 'daily', 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec', 'january', 'february', 'march', 'april', 'june', 'july', 'august', 'september', 'october', 'november', 'december' ]; // Convert to lowercase for case-insensitive comparison const lowerStreamId = streamId.toLowerCase().trim(); // Check exact matches if (insecurePatterns.includes(lowerStreamId)) { return true; } // Check patterns with numbers appended (e.g., guest1, user123) for (const pattern of insecurePatterns) { // Check if streamId starts with pattern followed by numbers const regex = new RegExp(`^${pattern}\\d+$`, 'i'); if (regex.test(lowerStreamId)) { return true; } } // Check for very short IDs (less than 4 characters) if (lowerStreamId.length < 4) { return true; } // Check for sequential numbers only if (/^\d+$/.test(lowerStreamId)) { return true; } // Check for single repeated character if (/^(.)\1+$/.test(lowerStreamId)) { return true; } return false; } /** * Creates and displays a security warning for insecure stream IDs * @param {string} message - The warning message to display * @param {number} duration - How long to show the warning (0 = until dismissed) * @returns {HTMLElement} - The warning element */ function showSecurityWarning(message, duration = 0) { // Remove any existing warnings const existingWarning = document.getElementById('stream-security-warning'); if (existingWarning) { existingWarning.remove(); } // Create warning container const warning = document.createElement('div'); warning.id = 'stream-security-warning'; warning.className = 'security-warning'; // Add critical inline styles as fallback warning.style.cssText = 'position: fixed; top: 20px; left: 50%; transform: translateX(-50%); background-color: #dc3545; color: white; padding: 16px 24px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); z-index: 10000; font-family: Arial, sans-serif; min-width: 350px; border: 2px solid #c82333;'; // Create warning content const content = document.createElement('div'); content.className = 'security-warning-content'; content.style.cssText = 'display: flex; align-items: center; gap: 12px;'; // Add warning icon const icon = document.createElement('span'); icon.className = 'security-warning-icon'; icon.innerHTML = '⚠️'; icon.style.cssText = 'font-size: 24px; flex-shrink: 0;'; // Add message const messageElement = document.createElement('span'); messageElement.className = 'security-warning-message'; messageElement.textContent = message; messageElement.style.cssText = 'flex-grow: 1; font-size: 16px; line-height: 1.5; font-weight: 500;'; // Add dismiss button const dismissButton = document.createElement('button'); dismissButton.className = 'security-warning-dismiss'; dismissButton.innerHTML = '×'; dismissButton.title = 'Dismiss warning'; dismissButton.style.cssText = 'background: none; border: none; color: white; font-size: 28px; cursor: pointer; padding: 0; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; opacity: 0.8; line-height: 1;'; dismissButton.onmouseover = () => dismissButton.style.opacity = '1'; dismissButton.onmouseout = () => dismissButton.style.opacity = '0.8'; dismissButton.onclick = () => warning.remove(); // Assemble warning content.appendChild(icon); content.appendChild(messageElement); content.appendChild(dismissButton); warning.appendChild(content); // Add to page document.body.appendChild(warning); // Auto-dismiss after duration if specified if (duration > 0) { setTimeout(() => { if (document.getElementById('stream-security-warning')) { warning.style.animation = 'fadeOut 0.3s ease-out'; setTimeout(() => warning.remove(), 300); } }, duration); } return warning; } /** * CSS styles for the security warning * This should be added to the page's stylesheet or injected dynamically */ const securityWarningStyles = ` `; // Function to inject styles if not already present function injectSecurityStyles() { if (!document.getElementById('security-warning-styles')) { // Create a proper style element const styleElement = document.createElement('style'); styleElement.id = 'security-warning-styles'; styleElement.textContent = securityWarningStyles.replace('', ''); document.head.appendChild(styleElement); } }