# Comment lire un rapport de violation CSP (/fr/blog/csp-violation-report-fields)



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](/fr/docs/web-security/reporting-api/reports/csp-violation) 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 [#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.

```json
{
  "type": "csp-violation",
  "age": 53,
  "url": "https://example.com/",
  "user_agent": "Mozilla/5.0 ...",
  "body": {
    "documentURL": "https://example.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://example.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.

```ts twoslash
// The body of a modern csp-violation report.
interface CspViolationBody {
  documentURL: string;
  referrer: string;
  blockedURL: string;
  effectiveDirective: string;
  originalPolicy: string;
  sourceFile: string;
  sample: string;
  disposition: "enforce" | "report";
  statusCode: number;
  lineNumber: number;
  columnNumber: number;
}

interface CspViolationReport {
  type: "csp-violation";
  age: number;
  url: string;
  user_agent: string;
  body: CspViolationBody;
}

function readViolation(report: CspViolationReport) {
  const blocked = report.body.blockedURL;
  const enforced = report.body.disposition === "enforce";
  return { blocked, enforced };
}
```

## La forme historique, report-uri [#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.

```json
{
  "csp-report": {
    "document-uri": "https://example.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](/fr/blog/report-uri-vs-report-to).

## Lire un rapport en pratique [#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](/fr/blog/debug-csp-violations-devtools).

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 [#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](/fr/docs/platform/monitoring/csp) sur lequel vous pouvez
agir, ce qui fait la différence entre collecter des rapports et les utiliser.

## Étapes suivantes [#étapes-suivantes]

* Mettez le reporting en place dans [Démarrer avec le reporting CSP](/fr/blog/get-started-csp-reporting).
* Voyez l'enveloppe dans [le format de livraison des rapports](/fr/docs/web-security/reporting-api/concepts/report-delivery-format).
* Resserrez la politique qui a produit ces rapports avec l'[évaluateur de CSP](/tools/csp-evaluator).

[Collectez et regroupez automatiquement les rapports CSP](/register).

## Sources [#sources]

* [W3C, CSP Level 3 - violation reports](https://www.w3.org/TR/CSP3/#create-violation-for-global)
* [W3C, Reporting API](https://www.w3.org/TR/reporting-1/)
* [MDN, CSPViolationReportBody](https://developer.mozilla.org/en-US/docs/Web/API/CSPViolationReportBody)
* [MDN, SecurityPolicyViolationEvent](https://developer.mozilla.org/en-US/docs/Web/API/SecurityPolicyViolationEvent)
