Content Security Policy and empty blocked-uri

Content Security Policy violation reports are usually very helpful in not only debugging your security policy, but actually for building it from scratch. There's however one case when they can be quite annoying...

Developing a CSP based on violation reports is something that does and it does its job quite well: whatever was reported as blocked will be presented to you for approval, and based on that a new policy is developed.

This works well for most policy items, such as images, styles, scripts etc. Except for two cases, where violation reports are quite useless: inline JavaScript and eval(). This is because for each of these distinctive events the browser will send identical report with empty blocked-uri field:

"referrer": "",
  "original-policy": "base-uri; connect-src 'none'; font-src 'none'; form-action 'none'; frame-ancestors 'none'; child-src 'none'; default-src 'none'; frame-src 'none'; img-src 'none'; media-src 'none'; object-src 'none'; script-src 'none'; style-src 'none';",
  "violated-directive": "script-src 'none'",
  "blocked-uri": "",
  "status-code": 200,
  "document-uri": ""

And there's nothing in there that could help us distinguish these two cases. You know it was something with JavaScript, but whether the website tried to use eval() or just had some inline code — you can't say without actually looking at the website's code or browser's console.

In CSP 1.0 this ambiguity only applied to script-src, but in CSP 1.1 also styles may need unsafe-eval if dynamic style generation features are used (and this was already observed in Chrome beta).

I have suggested a small improvement on this to the latest CSP 1.1 draft.