Start · Sprachen · JavaScript · Referenz · CSPViolationReport.originalPolicy

CSPViolationReport.originalPolicy

Eigenschaft

String mit der vollständigen Content Security Policy (CSP), deren Durchsetzung den gemeldeten Verstoß ausgelöst hat.

seit JavaScript Reporting API: Chromium-Browser (Chrome/Edge 96+); Kategorie: webapi

Signatur

CSPViolationReport.originalPolicy

Beschreibung

Die Eigenschaft originalPolicy des Wörterbuchs CSPViolationReport enthält die komplette Richtlinie als String, genau so, wie sie im Header Content-Security-Policy bzw. Content-Security-Policy-Report-Only oder im <meta http-equiv>-Element übermittelt wurde. Es ist also nicht nur die verletzte Direktive, sondern die gesamte Policy mit allen Direktiven.

Ein CSPViolationReport ist der body eines Berichts vom Typ "csp-violation" der Reporting API. Du bekommst ihn auf zwei Wegen: im Browser über einen ReportingObserver (dann als report.body.originalPolicy) oder auf dem Server als JSON, das der Browser per POST an den Endpunkt aus Reporting-Endpoints schickt, der in der Direktive report-to angegeben ist.

Nützlich ist die Eigenschaft vor allem dann, wenn mehrere Policys parallel gelten, zum Beispiel eine erzwungene und eine im Report-Only-Modus, oder wenn verschiedene Versionen einer Policy ausgerollt werden. Über originalPolicy ordnest du jeden Bericht eindeutig der Policy zu, die ihn ausgelöst hat. Zusammen mit effectiveDirective und disposition siehst du dann, welche Regel in welcher Policy gegriffen hat und ob wirklich blockiert ("enforce") oder nur gemeldet ("report") wurde.

Rückgabewert

Typ
string
Beschreibung
Die vollständige CSP als Zeichenkette, z. B. "default-src 'self'; img-src 'self' https://cdn.example.com; report-to csp-endpoint". Die Eigenschaft ist schreibgeschützt.

Beispiele

Verstöße im Browser mit ReportingObserver auslesen

// Seite ausgeliefert mit:
// Content-Security-Policy: default-src 'self'; img-src 'self'; report-to csp-endpoint
const observer = new ReportingObserver((reports) => {
  for (const report of reports) {
    const { originalPolicy, effectiveDirective, blockedURL } = report.body;
    console.log(`Verstoß gegen "${effectiveDirective}"`);
    console.log(`Blockiert: ${blockedURL}`);
    console.log(`Policy: ${originalPolicy}`);
  }
}, { types: ['csp-violation'], buffered: true });

observer.observe();

// Verstoß provozieren: Bild von fremder Domain laden
const img = new Image();
img.src = 'https://fremd.example.org/bild.png';
document.body.append(img);
Verstoß gegen "img-src" Blockiert: https://fremd.example.org/bild.png Policy: default-src 'self'; img-src 'self'; report-to csp-endpoint

Berichte serverseitig (Node.js/Express) nach Policy gruppieren

import express from 'express';

const app = express();
// Der Browser sendet Berichte als application/reports+json
app.use(express.json({ type: ['application/reports+json', 'application/json'] }));

const proPolicy = new Map();

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 policy = report.body.originalPolicy;
    proPolicy.set(policy, (proPolicy.get(policy) ?? 0) + 1);
  }
  res.sendStatus(204);
});

app.get('/csp-stats', (req, res) => {
  res.json(Object.fromEntries(proPolicy));
});

app.get('/', (req, res) => {
  res.set('Reporting-Endpoints', 'csp-endpoint="https://example.com/csp-reports"');
  res.set('Content-Security-Policy', "script-src 'self'; report-to csp-endpoint");
  res.send('<script src="https://cdn.fremd.org/x.js"></script>');
});

app.listen(3000);
GET /csp-stats → {"script-src 'self'; report-to csp-endpoint": 1}

Erzwungene und Report-Only-Policy auseinanderhalten

const ENFORCED = "default-src 'self'";

new ReportingObserver((reports) => {
  for (const { body } of reports) {
    const quelle = body.originalPolicy.startsWith(ENFORCED) && body.disposition === 'enforce'
      ? 'Produktiv-Policy'
      : 'Test-Policy (Report-Only)';
    console.log(`${quelle}: ${body.effectiveDirective} → ${body.blockedURL}`);
  }
}, { types: ['csp-violation'] }).observe();
Test-Policy (Report-Only): script-src-elem → https://cdn.fremd.org/x.js

// Wichtig · Fallstricke

  • Altes Format: Beim veralteten report-uri schickt der Browser ein anderes JSON (Content-Type: application/csp-report). Das Feld heißt dort "original-policy" in Kebab-Case und steckt im Objekt "csp-report". Ein Server, der beide Formate annimmt, muss beide Schreibweisen auswerten.
  • Browser-Unterstützung: report-to mit Reporting-Endpoints und ReportingObserver für CSP funktionieren zuverlässig nur in Chromium-Browsern. Für Firefox und Safari solltest du zusätzlich report-uri angeben oder das Event securitypolicyviolation nutzen.
  • Größe und Datenschutz: Die Policy kann lang sein und bei jedem Bericht erneut übertragen werden. Speichere sie serverseitig am besten gehasht oder normalisiert, statt sie in jedem Protokolleintrag zu wiederholen. Nonces in der Policy ('nonce-…') wechseln bei jeder Anfrage. Ersetze sie vor dem Gruppieren durch einen Platzhalter, sonst bekommst du für jede Anfrage eine eigene Gruppe.
  • Berichte sind vom Client kontrollierbare Eingaben. Validiere sie auf dem Server und gib originalPolicy in Admin-Oberflächen nie ungefiltert als HTML aus (XSS-Gefahr).
  • Berichte werden gebündelt und zeitverzögert zugestellt. Erwarte also keine Echtzeit.