Start · Sprachen · JavaScript · Referenz · CSPViolationReport.sample

CSPViolationReport.sample

Eigenschaft

String mit einem Ausschnitt (bis zu 40 Zeichen) des Inline-Skripts, Event-Handlers oder Styles, der einen CSP-Verstoß ausgelöst hat – sonst ein leerer String.

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

Signatur

CSPViolationReport.sample

Beschreibung

Die schreibgeschützte Eigenschaft sample des Wörterbuchs CSPViolationReport enthält einen kurzen Codeausschnitt der Ressource, die gegen die Content Security Policy verstoßen hat. Ein CSPViolationReport ist der Inhalt (body) eines Report-Objekts vom Typ "csp-violation". Solche Berichte werden über einen ReportingObserver gemeldet oder per Reporting-Endpoints-Header an einen Server geschickt.

Befüllt wird sample nur bei Inline-Verstößen, also bei blockierten <script>-Blöcken, Inline-Event-Handlern wie onclick="...", <style>-Blöcken und style-Attributen. Laut Spezifikation darf der Browser höchstens die ersten 40 Zeichen übernehmen. Bei eval()-Verstößen kann der Ausschnitt ebenfalls enthalten sein. Bei blockierten externen Ressourcen (z. B. <script src>) steht die Adresse in blockedURL und sample ist leer.

Wichtig: Der Ausschnitt wird nur übertragen, wenn die betroffene Direktive (z. B. script-src oder style-src) das Schlüsselwort 'report-sample' enthält. Fehlt es, ist sample immer ein leerer String. Der Ausschnitt hilft sehr bei der Fehlersuche: Man erkennt schnell, ob ein eigener Codeteil vergessen wurde, eine Browsererweiterung Code einschleust oder tatsächlich ein XSS-Versuch vorliegt.

Rückgabewert

Typ
string
Beschreibung
Die ersten (höchstens 40) Zeichen des Inline-Skripts, Event-Handlers oder Styles, der den Verstoß ausgelöst hat. Ein leerer String "", wenn 'report-sample' fehlt oder keine Inline-Ressource betroffen ist.

Beispiele

CSP-Header mit 'report-sample' und Reporting-Endpunkt

// Node.js / Express: CSP so setzen, dass Ausschnitte mitgeschickt werden
import express from 'express';

const app = express();

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

app.get('/', (req, res) => {
  // Dieses Inline-Skript wird blockiert und erzeugt einen Bericht
  res.send('<script>console.log("Hallo von einem Inline-Skript")</script>');
});

app.listen(3000);

Ausschnitt im Browser mit ReportingObserver auslesen

const observer = new ReportingObserver((reports) => {
  for (const report of reports) {
    const { effectiveDirective, sample, blockedURL } = report.body;
    console.log(`Direktive: ${effectiveDirective}`);
    console.log(`Blockiert: ${blockedURL}`);
    console.log(`Ausschnitt: ${sample || '(kein Ausschnitt)'}`);
  }
}, { types: ['csp-violation'], buffered: true });

observer.observe();
Direktive: script-src-elem Blockiert: inline Ausschnitt: console.log("Hallo von einem Inline-S

Berichte serverseitig auswerten und Ausschnitt protokollieren

import express from 'express';

const app = express();

// Die Reporting API sendet den 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, effectiveDirective, sample } = report.body;
      // Ausschnitt nur als Text protokollieren – niemals als HTML ausgeben!
      console.warn(
        `[CSP] ${documentURL} | ${effectiveDirective} | sample=${JSON.stringify(sample)}`
      );
    }
    res.sendStatus(204);
  }
);

app.listen(3000);
[CSP] http://localhost:3000/ | script-src-elem | sample="console.log(\"Hallo von einem Inline-S"

// Wichtig · Fallstricke

  • Ohne 'report-sample' kein Ausschnitt: Das Schlüsselwort muss in der Direktive stehen, gegen die verstoßen wird, also in script-src bzw. style-src oder den -elem/-attr-Varianten. Ein Eintrag nur in default-src reicht nicht, wenn eine speziellere Direktive gilt.
  • Höchstens 40 Zeichen: Der Ausschnitt wird abgeschnitten. Für eine eindeutige Zuordnung sollte man ihn mit sourceFile, lineNumber und columnNumber kombinieren.
  • Sicherheit: sample kann von Angreifern eingeschleusten Code enthalten. Den Wert in Admin-Oberflächen oder Log-Viewern daher nie ungeprüft per innerHTML ausgeben, sonst entsteht eine zweite XSS-Lücke. Außerdem können im Ausschnitt personenbezogene oder sensible Daten stecken (z. B. Tokens in Inline-Skripten). Das ist beim Speichern von Protokollen zu beachten (DSGVO).
  • Browser-Kompatibilität: ReportingObserver mit csp-violation und report-to werden vor allem von Chromium-Browsern unterstützt. Für andere Browser zusätzlich report-uri angeben: Dabei wird ein älteres JSON-Format mit dem Feld script-sample gesendet. Im Dokument selbst liefert das Ereignis securitypolicyviolation denselben Wert über SecurityPolicyViolationEvent.sample.
  • Im Modus Content-Security-Policy-Report-Only wird sample genauso befüllt. Damit lässt sich eine neue Richtlinie gefahrlos testen.