/** * Mercedes-Benz MYP Platform - CSP Violation Handler * Protokolliert und behandelt Content Security Policy Verletzungen */ class CSPViolationHandler { constructor() { this.violations = []; this.init(); } init() { // CSP Violation Event Listener document.addEventListener('securitypolicyviolation', this.handleViolation.bind(this)); // Report-To API fallback if ('ReportingObserver' in window) { const observer = new ReportingObserver((reports, observer) => { for (const report of reports) { if (report.type === 'csp-violation') { this.handleViolation(report.body); } } }); observer.observe(); } console.log('🛡️ CSP Violation Handler initialisiert'); } /** * CSP-Verletzung behandeln */ handleViolation(violationEvent) { const violation = { timestamp: new Date().toISOString(), blockedURI: violationEvent.blockedURI || 'unknown', violatedDirective: violationEvent.violatedDirective || 'unknown', originalPolicy: violationEvent.originalPolicy || 'unknown', documentURI: violationEvent.documentURI || window.location.href, sourceFile: violationEvent.sourceFile || 'unknown', lineNumber: violationEvent.lineNumber || 0, columnNumber: violationEvent.columnNumber || 0, sample: violationEvent.sample || '', disposition: violationEvent.disposition || 'enforce' }; this.violations.push(violation); this.logViolation(violation); this.suggestFix(violation); // Violation an Server senden (falls API verfügbar) this.reportViolation(violation); } /** * Verletzung protokollieren */ logViolation(violation) { console.group('🚨 CSP Violation detected'); console.error('Blocked URI:', violation.blockedURI); console.error('Violated Directive:', violation.violatedDirective); console.error('Source:', `${violation.sourceFile}:${violation.lineNumber}:${violation.columnNumber}`); console.error('Sample:', violation.sample); console.error('Full Policy:', violation.originalPolicy); console.groupEnd(); } /** * Lösungsvorschlag basierend auf Verletzungstyp */ suggestFix(violation) { const directive = violation.violatedDirective; const blockedURI = violation.blockedURI; console.group('💡 Lösungsvorschlag'); if (directive.includes('script-src')) { if (blockedURI === 'inline') { console.log('Problem: Inline-Script blockiert'); console.log('Lösung 1: Script in externe .js-Datei auslagern'); console.log('Lösung 2: data-action Attribute für Event-Handler verwenden'); console.log('Lösung 3: Nonce verwenden (nicht empfohlen für Entwicklung)'); console.log('Beispiel: '); } else if (blockedURI.includes('eval')) { console.log('Problem: eval() oder ähnliche Funktionen blockiert'); console.log('Lösung: Verwende sichere Alternativen zu eval()'); } else { console.log(`Problem: Externes Script von ${blockedURI} blockiert`); console.log('Lösung: URL zur CSP script-src Richtlinie hinzufügen'); } } else if (directive.includes('style-src')) { console.log('Problem: Style blockiert'); console.log('Lösung: CSS in externe .css-Datei auslagern oder CSP erweitern'); } else if (directive.includes('connect-src')) { console.log(`Problem: Verbindung zu ${blockedURI} blockiert`); console.log('Lösung: URL zur CSP connect-src Richtlinie hinzufügen'); console.log('Tipp: Für API-Calls relative URLs verwenden'); } else if (directive.includes('img-src')) { console.log(`Problem: Bild von ${blockedURI} blockiert`); console.log('Lösung: URL zur CSP img-src Richtlinie hinzufügen'); } console.groupEnd(); } /** * Verletzung an Server senden */ async reportViolation(violation) { try { // Nur in Produktion an Server senden if (window.location.hostname !== 'localhost' && window.location.hostname !== '127.0.0.1') { await fetch('/api/security/csp-violation', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(violation) }); } } catch (error) { console.warn('Fehler beim Senden der CSP-Verletzung:', error); } } /** * Alle Verletzungen abrufen */ getViolations() { return this.violations; } /** * Verletzungsstatistiken */ getStats() { const stats = { total: this.violations.length, byDirective: {}, byURI: {}, recent: this.violations.slice(-10) }; this.violations.forEach(violation => { // Nach Direktive gruppieren const directive = violation.violatedDirective; stats.byDirective[directive] = (stats.byDirective[directive] || 0) + 1; // Nach URI gruppieren const uri = violation.blockedURI; stats.byURI[uri] = (stats.byURI[uri] || 0) + 1; }); return stats; } /** * Entwickler-Debugging-Tools */ enableDebugMode() { // Debug-Panel erstellen this.createDebugPanel(); // Konsolen-Hilfe ausgeben console.log('🔧 CSP Debug Mode aktiviert'); console.log('Verfügbare Befehle:'); console.log('- cspHandler.getViolations() - Alle Verletzungen anzeigen'); console.log('- cspHandler.getStats() - Statistiken anzeigen'); console.log('- cspHandler.clearViolations() - Verletzungen löschen'); console.log('- cspHandler.exportViolations() - Als JSON exportieren'); } /** * Debug-Panel erstellen */ createDebugPanel() { const panel = document.createElement('div'); panel.id = 'csp-debug-panel'; panel.style.cssText = ` position: fixed; top: 10px; right: 10px; width: 300px; max-height: 400px; background: rgba(0, 0, 0, 0.9); color: white; font-family: monospace; font-size: 12px; padding: 10px; border-radius: 5px; z-index: 10000; overflow-y: auto; display: none; `; panel.innerHTML = `
CSP Violations
`; document.body.appendChild(panel); // Shortcut zum Anzeigen/Verstecken document.addEventListener('keydown', (event) => { if (event.ctrlKey && event.shiftKey && event.key === 'C') { panel.style.display = panel.style.display === 'none' ? 'block' : 'none'; this.updateDebugPanel(); } }); } /** * Debug-Panel aktualisieren */ updateDebugPanel() { const list = document.getElementById('csp-violations-list'); if (!list) return; const recent = this.violations.slice(-5); list.innerHTML = recent.map(v => `
${v.violatedDirective}
${v.blockedURI}
${v.timestamp}
`).join(''); } /** * Verletzungen löschen */ clearViolations() { this.violations = []; this.updateDebugPanel(); console.log('🗑️ CSP Violations gelöscht'); } /** * Verletzungen exportieren */ exportViolations() { const data = { timestamp: new Date().toISOString(), stats: this.getStats(), violations: this.violations }; const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `csp-violations-${new Date().toISOString().split('T')[0]}.json`; a.click(); URL.revokeObjectURL(url); console.log('📄 CSP Violations exportiert'); } } // Globale Instanz erstellen const cspHandler = new CSPViolationHandler(); // In Entwicklungsumgebung Debug-Mode aktivieren if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') { cspHandler.enableDebugMode(); console.log('🔍 CSP Debug Mode aktiv - Drücken Sie Ctrl+Shift+C für Debug-Panel'); } // Global verfügbar machen window.cspHandler = cspHandler; console.log('🛡️ CSP Violation Handler geladen');