Start · Sprachen · JavaScript · Referenz · CSPViolationReport

CSPViolationReport

Schnittstelle

Beschreibt einen Bericht der Reporting API, der erzeugt wird, wenn ein Dokument gegen seine Content Security Policy (CSP) verstößt.

seit JavaScript Reporting API: Chromium 96+ (ReportingObserver), F Kategorie: webapi

Signatur

interface CSPViolationReport { type: "csp-violation"; url: string; body: CSPViolationReportBody }

Beschreibung

CSPViolationReport ist ein Wörterbuch (Dictionary) der Reporting API, also kein Objekt, das man selbst per Konstruktor erzeugt. Der Browser legt es an, wenn eine Ressource, ein Inline-Skript, ein eval()-Aufruf o. ä. gegen die aktive Content-Security-Policy (oder Content-Security-Policy-Report-Only) verstößt. Der Bericht hat den Typ "csp-violation" und enthält im Feld body ein CSPViolationReportBody mit allen Details zum Verstoß.

Solche Berichte erreichen dich auf zwei Wegen:

  • Im Client über einen ReportingObserver mit types: ["csp-violation"]. Den Report bekommst du dort als Report-Objekt mit den Eigenschaften type, url und body.
  • Auf dem Server per HTTP-POST an einen Endpunkt, den du mit dem Header Reporting-Endpoints festlegst und in der CSP-Direktive report-to einträgst. Der Browser schickt dann ein JSON-Array mit dem Content-Type application/reports+json. Jedes Element darin hat zusätzlich die Felder age und user_agent.

Typische Anwendungen sind das Einführen einer CSP ohne Risiko: Man verteilt sie zuerst als Report-Only, sammelt die Verstöße und verschärft die Richtlinie danach. Außerdem eignen sich die Berichte, um XSS-Versuche oder unerwartete Drittanbieter-Skripte im Live-Betrieb zu erkennen. Die ältere Direktive report-uri liefert ein anderes JSON-Format (csp-report mit Feldnamen in kebab-case). CSPViolationReport ist das neue, einheitliche Format der Reporting API.

Parameter

Name Typ Default Beschreibung
$type Pflicht string "csp-violation" Berichtstyp, bei CSP-Verstößen immer "csp-violation".
$url Pflicht string URL des Dokuments, in dem der Verstoß aufgetreten ist.
$age number Nur im Server-Bericht: Millisekunden zwischen dem Erzeugen und dem Versenden des Berichts.
$user_agent string Nur im Server-Bericht: User-Agent-String des meldenden Browsers.
$body.blockedURL string Blockierte Ressource oder ein Schlüsselwort wie "inline", "eval", "wasm-eval", "trusted-types-policy".
$body.documentURL Pflicht string URL des Dokuments, dessen Richtlinie verletzt wurde.
$body.effectiveDirective Pflicht string Direktive, die tatsächlich gegriffen hat, z. B. "script-src-elem".
$body.originalPolicy Pflicht string Vollständiger Text der verletzten CSP.
$body.disposition Pflicht "enforce" | "report" "enforce": Die Ressource wurde blockiert. "report": Der Verstoß wurde nur gemeldet (Report-Only).
$body.sourceFile string | null null Datei, in der der Verstoß ausgelöst wurde.
$body.lineNumber number | null null Zeilennummer in sourceFile.
$body.columnNumber number | null null Spaltennummer in sourceFile.
$body.sample string "" Die ersten 40 Zeichen des blockierten Inline-Codes. Nur vorhanden, wenn die Direktive 'report-sample' enthält.
$body.referrer string | null Referrer des Dokuments.
$body.statusCode Pflicht number HTTP-Statuscode, mit dem das Dokument ausgeliefert wurde (z. B. 200).

Rückgabewert

Typ
CSPViolationReport
Beschreibung
Ein reines Datenobjekt. Der Browser übergibt es an den Callback eines ReportingObserver oder schickt es als JSON an den Reporting-Endpunkt.

Beispiele

CSP-Verstöße im Client mit ReportingObserver abfangen

// Seite mit Header: Content-Security-Policy: script-src 'self'
const observer = new ReportingObserver((reports) => {
  for (const report of reports) {
    const { blockedURL, effectiveDirective, disposition } = report.body;
    console.log(`${report.type}: ${blockedURL} verletzt ${effectiveDirective} (${disposition})`);
  }
}, { types: ['csp-violation'], buffered: true });

observer.observe();

// Löst einen Verstoß aus: fremdes Skript wird blockiert
const s = document.createElement('script');
s.src = 'https://evil.example/tracker.js';
document.head.append(s);
csp-violation: https://evil.example/tracker.js verletzt script-src-elem (enforce)

Reporting-Endpunkt per HTTP-Header einrichten (Node.js/Express)

import express from 'express';

const app = express();

app.use((req, res, next) => {
  res.setHeader('Reporting-Endpoints', 'csp-endpoint="https://example.com/csp-reports"');
  res.setHeader(
    'Content-Security-Policy-Report-Only',
    "default-src 'self'; script-src 'self' 'report-sample'; report-to csp-endpoint"
  );
  next();
});

// Browser sendet ein JSON-Array mit Content-Type application/reports+json
app.post('/csp-reports', express.json({ type: 'application/reports+json' }), (req, res) => {
  for (const report of req.body) {
    if (report.type !== 'csp-violation') continue;
    const { documentURL, blockedURL, effectiveDirective, sample } = report.body;
    console.warn('[CSP]', documentURL, '→', blockedURL, effectiveDirective, sample);
  }
  res.sendStatus(204);
});

app.listen(3000);
[CSP] https://example.com/ → inline script-src-elem console.log("hi")

Beispiel eines gesendeten CSPViolationReport-JSON

const beispielReport = [{
  age: 53531,
  type: 'csp-violation',
  url: 'https://example.com/seite.html',
  user_agent: 'Mozilla/5.0 (X11; Linux x86_64) Chrome/120.0',
  body: {
    blockedURL: 'inline',
    columnNumber: 39,
    disposition: 'enforce',
    documentURL: 'https://example.com/seite.html',
    effectiveDirective: 'script-src-elem',
    lineNumber: 121,
    originalPolicy: "script-src 'self' 'report-sample'; report-to csp-endpoint",
    referrer: 'https://www.google.com/',
    sample: 'console.log("lo")',
    sourceFile: 'https://example.com/seite.html',
    statusCode: 200
  }
}];

// Verstöße nach Direktive gruppieren
const proDirektive = Object.groupBy(beispielReport, (r) => r.body.effectiveDirective);
console.log(Object.keys(proDirektive));
[ 'script-src-elem' ]