Signatur
Beschreibung
Die Eigenschaft lineNumber gehört zum Dictionary CSPViolationReport. Das ist der Inhalt (body) eines Berichts vom Typ "csp-violation" aus der Reporting API. Sie enthält die Zeilennummer in der Datei aus sourceFile, an der die Content Security Policy verletzt wurde, zum Beispiel durch einen blockierten eval()-Aufruf, ein blockiertes Inline-Skript oder das Laden einer nicht erlaubten Ressource.
Zusammen mit sourceFile und columnNumber zeigt lineNumber genau auf die Codestelle, die den Verstoß verursacht hat. Das ist besonders hilfreich, wenn man eine strenge CSP zuerst im Modus Content-Security-Policy-Report-Only einführt und alle problematischen Stellen finden möchte, bevor die Richtlinie tatsächlich etwas blockiert.
Man stößt auf den Wert an zwei Stellen:
- Im Client über einen
ReportingObservermittypes: ["csp-violation"]. Dann ist er alsreport.body.lineNumbererreichbar. - Auf dem Server im JSON-Bericht, den der Browser an den Endpunkt aus der Direktive
report-to(definiert perReporting-Endpoints-Header) schickt. Dort steht er im Feldbody.lineNumber.
Die Eigenschaft ist schreibgeschützt und hat einen Wert von 1 aufwärts. Wenn der Browser keine Codestelle zuordnen kann, zum Beispiel bei Verstößen durch HTML-Attribute oder beim Laden von Ressourcen ohne Skriptkontext, ist der Wert null oder 0.
Rückgabewert
sourceFile, an der der Verstoß ausgelöst wurde. Ist keine Zuordnung möglich, ist der Wert null oder 0.Beispiele
CSP-Verstöße im Client mit ReportingObserver protokollieren
// Voraussetzung: Seite liefert z. B. den Header
// Content-Security-Policy: script-src 'self'
const observer = new ReportingObserver((reports) => {
for (const { type, body } of reports) {
if (type !== 'csp-violation') continue;
const ort = body.lineNumber
? `${body.sourceFile}:${body.lineNumber}:${body.columnNumber ?? 0}`
: '(keine Codestelle bekannt)';
console.warn(`CSP-Verstoß gegen ${body.effectiveDirective} bei ${ort}`);
}
}, { types: ['csp-violation'], buffered: true });
observer.observe();
// Löst einen Verstoß aus, falls 'unsafe-eval' nicht erlaubt ist
try { eval('1 + 1'); } catch (e) { /* EvalError durch CSP */ }
Berichte am Server-Endpunkt auswerten (Node.js/Express)
// Response-Header der Seite:
// Reporting-Endpoints: csp="https://example.com/csp-reports"
// Content-Security-Policy-Report-Only: script-src 'self'; report-to csp
import express from 'express';
const app = express();
app.use(express.json({ type: ['application/reports+json', 'application/json'] }));
app.post('/csp-reports', (req, res) => {
const reports = Array.isArray(req.body) ? req.body : [req.body];
for (const report of reports) {
if (report.type !== 'csp-violation') continue;
const { sourceFile, lineNumber, columnNumber, blockedURL } = report.body;
console.log(`Blockiert: ${blockedURL} – ${sourceFile ?? '?'}:${lineNumber ?? '?'}:${columnNumber ?? '?'}`);
}
res.sendStatus(204);
});
app.listen(3000);
Verstöße nach Codestelle gruppieren
// Fasst gleiche Verstöße zusammen, damit sie sich leichter aufräumen lassen
const gruppiereNachStelle = (bodies) => {
const zaehler = new Map();
for (const b of bodies) {
const key = `${b.sourceFile ?? 'unbekannt'}:${b.lineNumber ?? '-'}`;
zaehler.set(key, (zaehler.get(key) ?? 0) + 1);
}
return Object.fromEntries(zaehler);
};
const bodies = [
{ sourceFile: 'https://example.com/app.js', lineNumber: 14 },
{ sourceFile: 'https://example.com/app.js', lineNumber: 14 },
{ sourceFile: null, lineNumber: null }
];
console.log(gruppiereNachStelle(bodies));
// Wichtig · Fallstricke
- Browser-Unterstützung:
ReportingObserverund die Direktivereport-tomit dem HeaderReporting-Endpointswerden vor allem von Chromium-Browsern unterstützt. In anderen Browsern ist die Unterstützung lückenhaft. Zusätzlich die veraltete Direktivereport-urianzugeben, lohnt sich weiterhin. Dort heißt das Feld aberline-numberund steht im Objektcsp-report. - Kann fehlen: Den Wert immer auf
nullbzw.0prüfen. Bei blockierten Ressourcen ohne Skriptkontext gibt es keine Zeilennummer. - Cross-Origin-Skripte: Wenn der Verstoß aus einem fremden Skript ohne CORS stammt, können
sourceFile,lineNumberundcolumnNumberaus Datenschutzgründen gekürzt oder leer sein. - Minifizierter Code: In gebündelten Dateien zeigt die Zeilennummer auf die ausgelieferte Datei, nicht auf den Quellcode. Um die ursprüngliche Stelle zu finden, braucht man Source Maps.
- Nicht mit dem Event verwechseln:
SecurityPolicyViolationEvent.lineNumberliefert dieselbe Information, aber über das Eventsecuritypolicyviolation. - Sicherheit: Berichte am Endpunkt kommen vom Client und lassen sich fälschen. Die Felder deshalb vor dem Speichern oder Anzeigen prüfen und escapen.