Understanding CSP: report shows blocked that shouldn’t have been blocked


I’m having trouble making sense of some reported CSP violations that don’t seem to actually be violations according to the CSP standard. I have not managed to reproduce the violations in my own browser, and based on my own testing I believe that the block is the result of a non-compliant browser. That seems like a bold assertion, but based on all the documentation I’ve read and my tests it’s the only thing that makes sense.

Here is (more or less) what the CSP is:

frame-ancestors [list-of-urls]; default-src https: data: blob: 'unsafe-inline' 'unsafe-eval' [list-of-more-urls]; report-uri [my-reporting-endpoint] 

The problem is that I’m getting some violations sent to my reporting endpoint. Here is an example violation report:

{"csp-report":{     "document-uri":"[REDACTED]",     "referrer":"[REDACTED]",     "violated-directive":"script-src-elem",     "effective-directive":"script-src-elem",     "original-policy":"[SEE ABOVE]",     "disposition":"enforce",     "blocked-uri":"https://example.com/example.js",     "status-code":0,     "script-sample":"" }} 

The context would be that the page in question had a <script src="https://example.com/example.js"></script> on it somewhere.

To be clear, https://example.com is not in the list of allowed URLs under default-src. However, that shouldn’t really matter. Here are all the relevant facts that lead me to believe this is being caused by a non-compliant browser that someone is using:

  1. There is no script-src-elem defined so it should fall back on the default-src for the list of allowed URLs.
  2. default-src includes the https: schema, which means that all urls with an https scheme will be allowed. The blocked URL definitely uses HTTPS
  3. This source agrees that the scheme source (https) will automatically allow any https resources. Therefore this should be allowed even though example.com is not in the list of allowed URLs.
  4. The official CSP docs also agree, showing that scheme matching happens first and can allow a URL even before the list of allowed URLs is checked.
  5. Therefore, if you include the https: scheme in your default-src, your CSP will match <script src="https://anything.com"> even if not specifically in the list of allowed URLs
  6. In my own testing I found the above to be true.

Despite all of this, I have sporadic reports of CSP violations even though it shouldn’t. Note that I’m unable to replicate this exactly because the pages in question have changed, and I don’t have easy control over them. The only thing I can think of is that some of my users have a browser that isn’t properly adhering to the CSP standard, and are rejecting the URL since it is not on the list of allowed URLs, rather than allowing it based on its scheme.

Is this the best explanation, or am I missing something about my CSP? (and yes, I know that this CSP is not a very strict one).