diff --git a/app/helpers/defer_script_helper.rb b/app/helpers/defer_script_helper.rb new file mode 100644 index 00000000000..a33ba1d328d --- /dev/null +++ b/app/helpers/defer_script_helper.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# Helper to render a no-op inline script tag to work around a safari bug +# which causes `defer` scripts to be run before stylesheets are loaded. +# https://bugs.webkit.org/show_bug.cgi?id=209261 +module DeferScriptHelper + def self.safari_workaround_script + <<~HTML.html_safe + + HTML + end + + def self.fingerprint + @fingerprint ||= calculate_fingerprint + end + + private + + def self.raw_js + "/* Workaround for https://bugs.webkit.org/show_bug.cgi?id=209261 */" + end + + def self.calculate_fingerprint + "sha256-#{Digest::SHA256.base64digest(raw_js)}" + end +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index f5c4aff9b32..6777cea56c4 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -143,5 +143,7 @@ <%- if allow_plugins? %> <%= build_plugin_html 'server:before-body-close' %> <%- end %> + + <%= DeferScriptHelper.safari_workaround_script %> diff --git a/lib/content_security_policy/default.rb b/lib/content_security_policy/default.rb index a606ae2c89a..615feebc666 100644 --- a/lib/content_security_policy/default.rb +++ b/lib/content_security_policy/default.rb @@ -87,6 +87,7 @@ class ContentSecurityPolicy end sources << "'#{SplashScreenHelper.fingerprint}'" if SiteSetting.splash_screen + sources << "'#{DeferScriptHelper.fingerprint}'" end end