Comment lire un rapport de violation CSP
CentralCSP Team ·
Dernière mise à jour:
Vous avez activé le reporting de votre politique de sécurité du contenu (CSP), les rapports arrivent, et vous voilà devant du JSON à essayer de comprendre ce qui a bloqué quoi. Les noms de champs sont laconiques, certaines valeurs sont masquées, et le même événement peut arriver sous deux formes différentes selon la façon dont vous avez câblé le reporting. Voici un guide champ par champ d'un rapport de violation CSP pour que vous puissiez en lire un d'un coup d'œil et savoir quelle ligne de votre politique modifier.
Il existe deux formats pour le même événement sous-jacent. Le
rapport csp-violation moderne est
livré via la Reporting API dans le cadre d'un lot ; le format report-uri historique
est un objet unique que le navigateur envoie en POST de son côté. Ils transportent la
même information sous des noms de champs différents, donc une fois que vous savez lire
l'un, vous savez lire l'autre.
La forme moderne, csp-violation
Voici ce que vous obtenez quand la politique utilise la directive report-to. Le
navigateur livre un tableau avec Content-Type: application/reports+json, et les
données spécifiques à la CSP se trouvent dans body avec des noms de champs en
camelCase.
{
"type": "csp-violation",
"age": 53,
"url": "https://api-next.centralcsp.com/",
"user_agent": "Mozilla/5.0 ...",
"body": {
"documentURL": "https://api-next.centralcsp.com/",
"referrer": "https://www.google.com/",
"blockedURL": "https://apis.google.com/js/platform.js",
"effectiveDirective": "script-src-elem",
"originalPolicy": "default-src 'self'; report-to csp-endpoint",
"sourceFile": "https://api-next.centralcsp.com/",
"sample": "",
"disposition": "enforce",
"statusCode": 200,
"lineNumber": 1441,
"columnNumber": 59
}
}| Champ | Ce qu'il signifie |
|---|---|
documentURL | La page où la violation s'est produite. |
blockedURL | La ressource qui a été bloquée. En cross-origin, elle est tronquée au schéma, à l'hôte et au port. |
effectiveDirective | La directive qui s'est réellement déclenchée (par exemple script-src-elem). |
originalPolicy | Le texte complet de la politique appliquée par le navigateur. |
disposition | enforce pour une politique bloquante, report pour Report-Only. |
sample | Les ~40 premiers caractères du contenu inline incriminé, uniquement quand la directive porte 'report-sample'. |
statusCode | Le statut HTTP de la réponse du document. |
lineNumber / columnNumber | L'emplacement pour les violations inline. |
Deux de ces champs surprennent. blockedURL est délibérément masqué jusqu'à l'origine
pour les ressources cross-origin, donc vous voyez https://cdn.example/ plutôt que le
chemin exact ; c'est une mesure de confidentialité, pas un bug. Et effectiveDirective
est la directive précise qui s'est déclenchée, qui peut être plus fine que ce que vous
avez écrit : une balise <script> bloquée rapporte script-src-elem même si votre
politique ne définissait que script-src, parce que script-src est le repli dont la
directive plus fine hérite.
Si vous analysez ces données sur votre endpoint, voici le body moderne sous forme de
type TypeScript que vous pouvez déposer dans le handler. Survolez n'importe quel champ
pour voir son type ; disposition est une union des deux seules valeurs qu'il peut
prendre.
// The body of a modern csp-violation report.
interface CspViolationBody {
: string;
: string;
: string;
: string;
: string;
: string;
: string;
: "enforce" | "report";
: number;
: number;
: number;
}
interface CspViolationReport {
: "csp-violation";
: number;
: string;
: string;
: CspViolationBody;
}
function (: CspViolationReport) {
const = ..;
const = .. === "enforce";
return { , };
}La forme historique, report-uri
Quand la politique utilise la directive report-uri, le navigateur envoie en POST un
objet unique avec Content-Type: application/csp-report et des noms de champs en
kebab-case.
{
"csp-report": {
"document-uri": "https://api-next.centralcsp.com/",
"blocked-uri": "https://apis.google.com/js/platform.js",
"effective-directive": "script-src-elem",
"violated-directive": "script-src-elem",
"original-policy": "default-src 'self'; report-uri /csp-reports",
"disposition": "enforce",
"status-code": 200,
"script-sample": ""
}
}La correspondance est de un à un : blockedURL correspond à blocked-uri,
effectiveDirective à effective-directive, sample à script-sample, et ainsi de
suite. Le seul champ supplémentaire, violated-directive, est un alias historique de
effective-directive et peut être ignoré. Si votre endpoint accepte les deux formats,
faites une branche selon l'en-tête Content-Type. Quelle directive vous devriez
envoyer, et pourquoi vous envoyez souvent les deux, est traité dans
report-uri vs report-to.
Lire un rapport en pratique
Lisez effectiveDirective et blockedURL ensemble ; ce couple vous dit presque tout.
Une violation script-src pointant vers un hôte que vous reconnaissez (un CDN, un
fournisseur d'analytics) signifie généralement que votre politique est trop stricte et
que vous devez autoriser cette source. Une violation pointant vers un hôte que vous ne
reconnaissez pas, ou un sample inline que vous n'avez pas écrit, mérite une enquête
comme injection possible. Pour remonter d'une seule violation jusqu'à la ligne qui l'a
causée, déboguez les violations CSP dans les DevTools de Chrome.
Le champ sample est le plus utile pour les violations inline, mais il n'apparaît que
lorsque la directive porte le mot-clé 'report-sample', et il est plafonné à environ
40 caractères, assez pour identifier l'extrait, pas pour fuiter un secret.
disposition vous dit s'il s'agissait d'un vrai blocage (enforce) ou d'un essai à
blanc (report), ce qui compte quand vous exécutez une politique appliquée et une
politique Report-Only en même temps.
Traitez chaque champ comme une entrée influencée par un attaquant. Un rapport est une
donnée que la page a poussé le navigateur à envoyer, donc n'affichez jamais blockedURL
ou sample sur une page d'administration sans échappement.
Arrêtez de lire du JSON brut
Lire un rapport, c'est bien ; en lire des milliers, non. CentralCSP ingère les deux formes, les normalise dans un seul modèle, et regroupe les violations par directive et par hôte bloqué, donc au lieu d'un fichier de log vous obtenez une liste classée de ce qui casse vraiment et à quelle fréquence. Elle les affiche sur un dashboard sur lequel vous pouvez agir, ce qui fait la différence entre collecter des rapports et les utiliser.
Étapes suivantes
- Mettez le reporting en place dans Démarrer avec le reporting CSP.
- Voyez l'enveloppe dans le format de livraison des rapports.
- Resserrez la politique qui a produit ces rapports avec l'évaluateur de CSP.
Collectez et regroupez automatiquement les rapports CSP.