Start · Sprachen · JavaScript · Referenz · COEPViolationReport

COEPViolationReport

Schnittstelle

Beschreibt einen Bericht der Reporting API, der erzeugt wird, wenn ein Dokument gegen seine <code>Cross-Origin-Embedder-Policy</code> (COEP) verstößt.

seit JavaScript Chromium-basierte Browser (Chrome/Edge 96+ mit Rep Kategorie: webapi

Signatur

dictionary COEPViolationReport { type: "coep"; url: string; body: COEPViolationReportBody }

Beschreibung

COEPViolationReport ist ein Wörterbuch (Dictionary) der Reporting API und keine Klasse, die man im Skript instanziiert. Es beschreibt die Struktur des JSON-Berichts, den der Browser erzeugt, wenn eine Ressource oder eine Navigation die Cross-Origin-Embedder-Policy des Dokuments verletzt. Das passiert zum Beispiel, wenn eine Seite mit require-corp ein fremdes Bild ohne Cross-Origin-Resource-Policy-Header oder ohne CORS lädt.

Wichtig ist COEP vor allem für die Cross-Origin-Isolation: Nur wenn COEP zusammen mit Cross-Origin-Opener-Policy: same-origin gesetzt ist, stehen Funktionen wie SharedArrayBuffer oder hochauflösende Timer zur Verfügung. Mit Verstoßberichten findest du heraus, welche eingebetteten Ressourcen bei der Umstellung kaputtgehen würden. Mit Cross-Origin-Embedder-Policy-Report-Only geht das sogar, ohne dass etwas blockiert wird.

Die Berichte stellt der Browser per POST mit dem Content-Type application/reports+json an einen Endpunkt zu, den du über den Header Reporting-Endpoints festlegst und in der COEP-Direktive mit report-to="name" auswählst. Das Feld body enthält die Details: den Verstoßtyp (corp, navigation oder worker-initialization), die blockierte URL, die Ziel-Art der Anfrage (destination) und ob die Richtlinie durchgesetzt oder nur gemeldet wurde (disposition).

Parameter

Name Typ Default Beschreibung
$type Pflicht "coep" Berichtstyp. Bei COEP-Verstößen immer "coep".
$url Pflicht string URL des Dokuments, in dem der Verstoß aufgetreten ist.
$body Pflicht object Details zum Verstoß (siehe die folgenden body.*-Felder).
$body.type Pflicht "corp" | "navigation" | "worker-initialization" Art des Verstoßes: corp = eine Subressource ohne passendes CORP/CORS wurde blockiert, navigation = ein eingebetteter Frame erfüllt die COEP nicht, worker-initialization = das Worker-Skript hat eine unpassende COEP.
$body.blockedURL Pflicht string URL der blockierten (bzw. im Report-Only-Modus nur gemeldeten) Ressource.
$body.disposition Pflicht "enforce" | "reporting" enforce: Die Ressource wurde tatsächlich blockiert. reporting: Der Verstoß kam über Cross-Origin-Embedder-Policy-Report-Only und wurde nur gemeldet.
$body.destination string Ziel-Art der Anfrage wie Request.destination, z. B. "image", "script" oder "iframe". Fehlt bei navigation-Berichten.
$age number Nur in der zugestellten JSON-Nutzlast: Millisekunden zwischen dem Verstoß und dem Versand.
$user_agent string Nur in der zugestellten JSON-Nutzlast: User-Agent-String des meldenden Browsers.

Rückgabewert

Typ
COEPViolationReport
Beschreibung
Ein reines Datenobjekt (in der Praxis ein Element im JSON-Array, das an den Reporting-Endpunkt gesendet wird). Es hat keine Methoden.

Beispiele

COEP mit Berichts-Endpunkt per Node.js-Header setzen

import http from 'node:http';

const server = http.createServer((req, res) => {
  // Endpunkt benennen
  res.setHeader('Reporting-Endpoints', 'coep-endpoint="https://example.com/reports"');
  // Nur melden, noch nicht blockieren – gut für die Umstellung
  res.setHeader(
    'Cross-Origin-Embedder-Policy-Report-Only',
    'require-corp; report-to="coep-endpoint"'
  );
  res.setHeader('Content-Type', 'text/html; charset=utf-8');
  res.end('<img src="https://cdn.other.example/logo.png">');
});

server.listen(3000, () => console.log('Server läuft auf Port 3000'));
Server läuft auf Port 3000

Beispielhafte Nutzlast eines COEP-Berichts

// So sieht der POST-Body (application/reports+json) aus, den der Browser sendet
const payload = [
  {
    age: 12,
    type: 'coep',
    url: 'https://example.com/',
    user_agent: 'Mozilla/5.0 ... Chrome/124.0',
    body: {
      type: 'corp',
      blockedURL: 'https://cdn.other.example/logo.png',
      destination: 'image',
      disposition: 'reporting'
    }
  }
];

const [report] = payload;
console.log(`${report.body.type}: ${report.body.blockedURL} (${report.body.destination})`);
corp: https://cdn.other.example/logo.png (image)

Berichte am Endpunkt empfangen und auswerten (Express)

import express from 'express';

const app = express();
app.use(express.json({ type: 'application/reports+json' }));

app.post('/reports', (req, res) => {
  const reports = Array.isArray(req.body) ? req.body : [];
  for (const r of reports.filter((r) => r.type === 'coep')) {
    const { type, blockedURL, destination, disposition } = r.body;
    console.warn(
      `[COEP ${disposition}] ${type} auf ${r.url}: ${blockedURL} (${destination ?? '-'})`
    );
  }
  res.sendStatus(204);
});

app.listen(8080);
[COEP reporting] corp auf https://example.com/: https://cdn.other.example/logo.png (image)

// Wichtig · Fallstricke

  • Nicht über ReportingObserver sichtbar: COEP-Berichte gehen nur an serverseitige Endpunkte und lassen sich im Skript nicht abfangen.
  • Browser-Unterstützung: Die Berichte gibt es praktisch nur in Chromium-basierten Browsern. Firefox und Safari unterstützen COEP selbst, senden aber keine solchen Berichte. Ältere Chrome-Versionen nutzten statt Reporting-Endpoints den veralteten Header Report-To.
  • Berichte werden gebündelt und verzögert versendet, auch nach dem Schließen der Seite. Der Endpunkt muss HTTPS nutzen. Wenn er auf einem anderen Ursprung liegt, muss er CORS-Preflight-Anfragen (OPTIONS) beantworten.
  • Mit credentialless statt require-corp verursachen No-CORS-Anfragen ohne Anmeldedaten keine Verstöße. Dadurch gibt es deutlich weniger Berichte.
  • Datenschutz: blockedURL und url können Tokens oder personenbezogene Query-Parameter enthalten. Kürze oder anonymisiere sie deshalb vor dem Speichern.
  • Prüfe eingehende Daten immer: Der Endpunkt ist öffentlich, und jeder kann gefälschte Berichte senden.