Firefox Vs. CSP

There is a thing called Content-Security-Policy, and that thing is basically a set of HTTP headers that describes what a browser should and should not do on a given page. A very useful thing it is, I must say, if you need to do some security.

Say, you want JavaScript on your site. Well, you don’t—naturally—because why would you, but you can’t do without it just yet. Even this blog has two of those: one for showing you webmentions, and another one for rendering nice Font Awesome icons. JavaScript plus third party content (like webmentions) is obviously a gaping hole in security, so you don’t want any sideloaded JavaScript to run on your site. That’s why CSP was invented.

As of today, CSP 2 has “recommended” state and all the main browsers can do it. You just add an HTTP-header like

Content-Security-Policy:
    script-src 'self' https://use.fontawesome.com;

and you’re done. The browser will only load the scripts hosted on your domain or Font Awesome’s (that you trust).

Well, you can relax about your own domain (you do use TLS, don’t you?), but a third-party domain is a threat, even if it is known and respected: you can’t be sure it won’t be hacked, and you can’t be sure DNS won’t be spoofed. That’s why SRI exists: you tell a browser the hash of the known script, and in case the script is replaced with something else the browser will not run it. You can define the hashes for allowed scripts in CSP version 2, but only for the local scripts hosted in your domain; in version 3 of CSP you can also define hashes for external scripts.

Trouble is, if you just add the hashes for your two scripts:

Content-Security-Policy:
script-src 'self' https://use.fontawesome.com
'sha384-VVrFY3uko2fhW05NnpTajhCiU9sSLrjZhyJ5K7w0mMphl16HrWuxyfAfMhC4G+xK'
'sha384-ZbbbT1gw3joYkKRqh0kWyRp32UAvdqkpbLedQJSlnI8iLQcFVxaGyrOgOJiDQTTR';

nothing changes. A browser has no way of knowing you meant CSP version 3. This header is perfectly valid for CSP version 2 as well, meaning “only load local scripts with these two hashes, and any scripts from Font Awesome are also OK”. And naturally as long as CSP ver. 2 is recommended a sane browser will prefer to err on this side and not break your site trying to match external scripts to those hashes.

What do you do? You simply add an attribute that is specific to CSP version 3—this way a browser that supports this version will know to ignore the domains directive (it must, by the spec) and only load the two scripts you need.

Content-Security-Policy:
script-src 'self' https://use.fontawesome.com
'sha384-VVrFY3uko2fhW05NnpTajhCiU9sSLrjZhyJ5K7w0mMphl16HrWuxyfAfMhC4G+xK'
'sha384-ZbbbT1gw3joYkKRqh0kWyRp32UAvdqkpbLedQJSlnI8iLQcFVxaGyrOgOJiDQTTR'
'strict-dynamic';

The 'strict-dynamic' attribute doesn’t change much by itself, it only tells the browser that the allowed scripts are allowed to load other scripts, which can be handy sometimes. No additional security threat here: you did read the script before hashing and allowing it, didn’t you? No surprises, then.

Well, there is one: Firefox wouldn’t run the Font Awesome script with this header. Why? Well, because Firefox developers use their butts instead of their brains.

You see, Firefox only partially supports CSP version 3. That is, it knows what 'strict-dynamic' means and knows it’s dealing with CSP ver. 3. And it knows that a browser must ignore domains directive in version 3. But checking external scripts’ hashes is something Firefox can’t do yet, so it won’t allow the script by the domain and won’t allow it by hash, so your user won’t have any icons!

The bug report in Firefox’s tracker is three years old. Three months ago someone smart enough came by and figured out that this breaks the spec-adhering websites and something should better be done about it. Well, they were able to move this bug from “defect” to “task”, at least.

No such shit happened with Eich around…

Comments can be sent as webmentions or by email.