| 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 | ||
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!)
Pull request: https://github.com/webkit/WebKit/pull/2526 Wrote this a few weeks ago, finally got around to posting it. 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. I hacked at export-w3c-test-changes and got it to create a PR. https://github.com/web-platform-tests/wpt/pull/34902 Committed 255611@main (2142cd8c9e15): <https://commits.webkit.org/255611@main> Reviewed commits have been landed. Closing PR #2526 and removing active labels. |
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?