Bug 233071

Summary: Allowlisting empty elements via content hashes in CSP directives is inconsistent across browser engines
Product: WebKit Reporter: Andy Bonventre <andybons>
Component: WebKit Misc.Assignee: Matthew Finkel <m_finkel>
Status: RESOLVED FIXED    
Severity: Normal CC: bfulgham, gsnedders, katherine_cheney, m_finkel, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Local Build   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://github.com/web-platform-tests/wpt/pull/34902

Description Andy Bonventre 2021-11-12 13:45:59 PST
The following page will render a red background on Chromium and Gecko, but not WebKit due to a CSP violation:

<!DOCTYPE html>
<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'self'; style-src 'self' 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='; script-src 'unsafe-inline'"
/>
<html lang="en">
  <script type="module">
    const style = document.createElement("style");
    style.appendChild(document.createTextNode(""));
    document.head.appendChild(style);
    const { sheet } = style;
    if (sheet) {
      sheet.insertRule("body { background: red; }");
      console.info("background should be red now");
    } else {
      console.error("no sheet found :(");
    }
  </script>
</html>

The <style> node is empty, so the sha256 of the empty string (sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=) allows for it to successfully apply to the page on Chromium and Gecko.

On WebKit, ContentSecurityPolicy::findHashOfContentInPolicies will always return false for an empty style element (see https://sourcegraph.com/github.com/WebKit/WebKit/-/blob/Source/WebCore/page/csp/ContentSecurityPolicy.cpp?L362)

A workaround on WebKit is to append some arbitrary content to the <style> tag:

<!DOCTYPE html>
<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'self'; style-src 'self' 'sha256-0hAheEzaMe6uXIKV4EehS9pu1am1lj/KnnzrOYqckXk='; script-src 'unsafe-inline'"
/>
<html lang="en">
  <script type="module">
    const style = document.createElement("style");
    style.appendChild(document.createTextNode("/**/"));
    document.head.appendChild(style);
    const { sheet } = style;
    if (sheet) {
      sheet.insertRule("body { background: red; }");
      console.info("background should be red now");
    } else {
      console.error("no sheet found :(");
    }
  </script>
</html>

From Kate Cheney in WebKit Slack:

> After a brief look at the spec, the empty string hash case doesn't seem to be explicitly talked about, but I don't see a reason here why we shouldn't match behavior of other major browsers. Could you file a bug on https://bugs.webkit.org about this?
Comment 1 Radar WebKit Bug Importer 2021-11-12 13:47:23 PST
<rdar://problem/85356188>
Comment 2 Sam Sneddon [:gsnedders] 2021-11-15 03:58:30 PST
From Kate:

> After a brief look at the spec, the empty string hash case doesn't seem to be explicitly talked about, but I don't see a reason here why we shouldn't match behavior of other major browsers.

That implies per spec that the empty string is just another string, no? If it isn't special-cased, then it's just another length of string, hence this is both "match the spec and match other browsers".

(Also a WPT test for this would be nice, if there isn't already one!)
Comment 3 Matthew Finkel 2022-07-18 15:15:31 PDT
Pull request: https://github.com/webkit/WebKit/pull/2526
Comment 4 Matthew Finkel 2022-07-18 15:16:10 PDT
Wrote this a few weeks ago, finally got around to posting it.
Comment 5 Matthew Finkel 2022-07-18 15:44:01 PDT
And, because I didn't actually say this in the previous comment:

This bug is not present in trunk. It was (possibly accidentally) fixed as part of https://bugs.webkit.org/show_bug.cgi?id=235199

Canonical link: https://commits.webkit.org/246139@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@288132 268f45cc-cd09-0410-ab3c-d52691b4dbfc

The PR is adding a WPT test, as Sam suggested.
Comment 6 Matthew Finkel 2022-07-19 11:57:40 PDT
I hacked at export-w3c-test-changes and got it to create a PR.

https://github.com/web-platform-tests/wpt/pull/34902
Comment 7 EWS 2022-10-16 22:12:18 PDT
Committed 255611@main (2142cd8c9e15): <https://commits.webkit.org/255611@main>

Reviewed commits have been landed. Closing PR #2526 and removing active labels.