DEV: Automatically extend CSP when themes link to external scripts (#9531)

This commit is contained in:
David Taylor 2020-04-24 09:47:01 +01:00 committed by GitHub
parent 90d6816d19
commit 8a112b7464
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 1 deletions

View File

@ -317,6 +317,7 @@ class ThemeField < ActiveRecord::Base
self.value_baked, self.error = translation_field? ? process_translation : process_html(self.value)
self.error = nil unless self.error.present?
self.compiler_version = COMPILER_VERSION
CSP::Extension.clear_theme_extensions_cache!
elsif extra_js_field?
self.value_baked, self.error = process_extra_js(self.value)
self.error = nil unless self.error.present?

View File

@ -42,7 +42,9 @@ class ContentSecurityPolicy
def find_theme_extensions(theme_ids)
extensions = []
Theme.where(id: Theme.transform_ids(theme_ids)).find_each do |theme|
resolved_ids = Theme.transform_ids(theme_ids)
Theme.where(id: resolved_ids).find_each do |theme|
theme.cached_settings.each do |setting, value|
extensions << build_theme_extension(value.split("|")) if setting.to_s == THEME_SETTING
end
@ -50,6 +52,21 @@ class ContentSecurityPolicy
extensions << build_theme_extension(ThemeModifierHelper.new(theme_ids: theme_ids).csp_extensions)
html_fields = ThemeField.where(
theme_id: resolved_ids,
target_id: ThemeField.basic_targets.map { |target| Theme.targets[target.to_sym] },
name: ThemeField.html_fields
)
auto_script_src_extension = { script_src: [] }
html_fields.each(&:ensure_baked!)
doc = html_fields.map(&:value_baked).join("\n")
Nokogiri::HTML.fragment(doc).css('script[src]').each do |node|
auto_script_src_extension[:script_src] << node['src']
end
extensions << auto_script_src_extension
extensions
end

View File

@ -212,6 +212,19 @@ describe ContentSecurityPolicy do
expect(parse(theme_policy)['script-src']).to_not include('https://from-theme-flag.script')
expect(parse(theme_policy)['worker-src']).to_not include('from-theme-flag.worker')
end
it 'is extended automatically when themes reference external scripts' do
policy # call this first to make sure further actions clear the cache
theme.set_field(target: :common, name: "header", value: "<script src='https://example.com/myscript.js'/>")
theme.save!
expect(parse(theme_policy)['script-src']).to include('https://example.com/myscript.js')
theme.destroy!
expect(parse(theme_policy)['script-src']).to_not include('https://example.com/myscript.js')
end
end
it 'can be extended by site setting' do