Web Worker security is an important concern for developers, especially when handling sensitive data or making cross-origin requests.
Major Security Considerations
1. Same-Origin Policy
Web Workers follow the same-origin policy and can only load scripts from the same origin as the main page.
javascript// ❌ Cross-origin loading of Worker - will fail const worker = new Worker('https://malicious-site.com/worker.js'); // ✅ Same-origin loading of Worker - works normally const worker = new Worker('/workers/worker.js'); // ✅ Use Blob URL to bypass (but content still needs to be same-origin) const workerCode = fetch('/trusted-source/worker.js') .then(response => response.text()) .then(code => { const blob = new Blob([code], { type: 'application/javascript' }); return new Worker(URL.createObjectURL(blob)); });
2. Data Isolation
Workers run in independent threads and cannot directly access main thread variables and DOM.
javascript// Main thread const secretData = 'sensitive information'; const worker = new Worker('worker.js'); // Worker cannot directly access secretData // worker.js console.log(secretData); // ReferenceError: secretData is not defined // ✅ Pass data through messages (note data will be deep cloned) worker.postMessage({ data: secretData });
3. Message Passing Security
When using postMessage to pass data, the data is structurally cloned.
javascript// ❌ Unsafe message passing worker.postMessage({ password: userPassword, token: authToken }); // ✅ Safe message passing - only pass necessary data worker.postMessage({ taskId: generateId(), encryptedData: encryptData(data) }); // ✅ Use Transferable Objects to avoid data copying const buffer = new ArrayBuffer(1024); worker.postMessage({ buffer }, [buffer]); // buffer is now empty, data has been transferred
4. Prevent XSS Attacks
Avoid executing untrusted code in Workers.
javascript// ❌ Dangerous: execute user input code const userCode = getUserInput(); const blob = new Blob([userCode], { type: 'application/javascript' }); const worker = new Worker(URL.createObjectURL(blob)); // ✅ Safe: use predefined Worker script const worker = new Worker('/trusted-worker.js'); worker.postMessage({ userInput: getUserInput() });
5. CORS Configuration
If you need to load Worker resources cross-origin, you need to configure CORS correctly.
javascript// Server needs to set CORS headers // Access-Control-Allow-Origin: https://your-domain.com // Access-Control-Allow-Methods: GET, POST // Access-Control-Allow-Headers: Content-Type // Client const worker = new Worker('https://api.example.com/worker.js');
Security Best Practices
1. Input Validation
javascript// worker.js self.onmessage = function(e) { const data = e.data; // Validate input data if (!isValidInput(data)) { console.error('Invalid input detected'); return; } // Process data const result = processData(data); self.postMessage(result); }; function isValidInput(data) { // Check data type if (typeof data !== 'object' || data === null) { return false; } // Check required fields if (!data.type || !data.payload) { return false; } // Check data size if (JSON.stringify(data).length > MAX_SIZE) { return false; } return true; }
2. Error Handling
javascript// Main thread const worker = new Worker('worker.js'); worker.onerror = function(event) { console.error('Worker error:', event.message); // Log error information (don't expose sensitive information) logError({ message: sanitizeErrorMessage(event.message), filename: event.filename, lineno: event.lineno }); // Take appropriate measures based on error type if (isSecurityError(event.error)) { terminateWorker(); } }; function sanitizeErrorMessage(message) { // Remove parts that may contain sensitive information return message.replace(/password|token|secret/gi, '[REDACTED]'); }
3. Resource Limits
javascript// worker.js const MAX_EXECUTION_TIME = 5000; // 5 seconds let startTime = null; self.onmessage = function(e) { startTime = performance.now(); try { const result = processWithTimeout(e.data, MAX_EXECUTION_TIME); self.postMessage(result); } catch (error) { if (error instanceof TimeoutError) { self.postMessage({ error: 'Operation timed out' }); } else { self.postMessage({ error: 'Processing failed' }); } } }; function processWithTimeout(data, timeout) { const result = []; for (let i = 0; i < data.length; i++) { // Check if timeout if (performance.now() - startTime > timeout) { throw new TimeoutError(); } result.push(processItem(data[i])); } return result; }
4. Message Encryption
javascript// Use Web Crypto API to encrypt sensitive data async function encryptData(data, key) { const encoder = new TextEncoder(); const encodedData = encoder.encode(data); const iv = crypto.getRandomValues(new Uint8Array(12)); const encrypted = await crypto.subtle.encrypt( { name: 'AES-GCM', iv: iv }, key, encodedData ); return { encrypted, iv }; } // Main thread const key = await crypto.subtle.generateKey( { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt'] ); const encrypted = await encryptData(sensitiveData, key); worker.postMessage({ encrypted, iv });
5. Worker Pool Management
javascriptclass SecureWorkerPool { constructor(workerPath, poolSize = 4) { this.workerPath = workerPath; this.poolSize = poolSize; this.workers = []; this.taskQueue = []; this.init(); } init() { for (let i = 0; i < this.poolSize; i++) { const worker = new Worker(this.workerPath); // Add error handling worker.onerror = (event) => { this.handleWorkerError(event, worker); }; worker.onmessage = (e) => this.handleMessage(e, worker); this.workers.push({ worker, busy: false, id: i }); } } handleWorkerError(event, workerObj) { console.error(`Worker ${workerObj.id} error:`, event.message); // Restart Worker this.restartWorker(workerObj); } restartWorker(workerObj) { const oldWorker = workerObj.worker; oldWorker.terminate(); const newWorker = new Worker(this.workerPath); newWorker.onerror = (event) => this.handleWorkerError(event, workerObj); newWorker.onmessage = (e) => this.handleMessage(e, workerObj); workerObj.worker = newWorker; workerObj.busy = false; } execute(data) { return new Promise((resolve, reject) => { // Validate input if (!this.validateInput(data)) { reject(new Error('Invalid input')); return; } const availableWorker = this.workers.find(w => !w.busy); if (availableWorker) { availableWorker.busy = true; availableWorker.worker.postMessage({ data, resolve, reject }); } else { this.taskQueue.push({ data, resolve, reject }); } }); } validateInput(data) { // Implement input validation logic return true; } }
Content Security Policy (CSP)
Configure CSP to restrict Worker behavior:
html<!-- Add CSP in HTML head --> <meta http-equiv="Content-Security-Policy" content="worker-src 'self' https://trusted-domain.com">
javascript// Check if Worker is restricted by CSP if (self.isSecureContext) { console.log('Worker is running in secure context'); }
Security Checklist
- Validate all input data
- Use HTTPS to load Worker scripts
- Follow same-origin policy
- Avoid executing untrusted code in Workers
- Implement error handling and logging
- Limit Worker execution time
- Encrypt sensitive data
- Configure appropriate CSP policies
- Regularly update Worker code
- Monitor Worker behavior and performance
Common Security Vulnerabilities
1. Data Leakage
javascript// ❌ Leak sensitive information worker.postMessage({ password: userPassword }); // ✅ Use encryption const encrypted = await encryptPassword(userPassword); worker.postMessage({ encrypted });
2. Denial of Service Attack
javascript// ❌ Unrestricted processing worker.postMessage(hugeData); // ✅ Limit data size if (data.length > MAX_SIZE) { throw new Error('Data too large'); }
3. Code Injection
javascript// ❌ Execute user code eval(userCode); // ✅ Use sandbox environment const sandbox = createSandbox(); sandbox.execute(userCode);
Best Practices Summary
- Input Validation: Strictly validate all input data
- Error Handling: Comprehensive error handling mechanisms
- Resource Limits: Limit execution time and data size
- Data Encryption: Use encrypted transmission for sensitive data
- HTTPS: Use HTTPS to load Worker scripts
- CSP Configuration: Configure appropriate content security policies
- Regular Audits: Regularly review Worker code security
- Monitoring Logs: Monitor Worker behavior and log events