Signatur
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
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'));
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})`);
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);
// Wichtig · Fallstricke
- Nicht über
ReportingObserversichtbar: 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-Endpointsden veralteten HeaderReport-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
credentiallessstattrequire-corpverursachen No-CORS-Anfragen ohne Anmeldedaten keine Verstöße. Dadurch gibt es deutlich weniger Berichte. - Datenschutz:
blockedURLundurlkö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.