discourse/lib/content_security_policy/default.rb
David Taylor 0f8e4d7acc
DEV: Compile splash screen JS with ember-cli before inlining (#18150)
This lets us use all our normal JS tooling like prettier, esline and babel on the splash screen JS. At runtime the JS file is read and inlined into the HTML. This commit also switches us to use a CSP hash rather than a nonce for the splash screen.
2022-09-01 09:58:48 +01:00

107 lines
3.4 KiB
Ruby

# frozen_string_literal: true
require 'content_security_policy'
class ContentSecurityPolicy
class Default
attr_reader :directives
def initialize(base_url:)
@base_url = base_url
@directives = {}.tap do |directives|
directives[:upgrade_insecure_requests] = [] if SiteSetting.force_https
directives[:base_uri] = [:self]
directives[:object_src] = [:none]
directives[:script_src] = script_src
directives[:worker_src] = worker_src
directives[:report_uri] = report_uri if SiteSetting.content_security_policy_collect_reports
directives[:frame_ancestors] = frame_ancestors if restrict_embed?
directives[:manifest_src] = ["'self'"]
end
end
private
def base_url
@base_url
end
SCRIPT_ASSET_DIRECTORIES = [
# [dir, can_use_s3_cdn, can_use_cdn, for_worker]
['/assets/', true, true, true],
['/brotli_asset/', true, true, true],
['/extra-locales/', false, false, false],
['/highlight-js/', false, true, false],
['/javascripts/', false, true, true],
['/plugins/', false, true, true],
['/theme-javascripts/', false, true, false],
['/svg-sprite/', false, true, false],
]
def script_assets(base = base_url, s3_cdn = GlobalSetting.s3_cdn_url, cdn = GlobalSetting.cdn_url, worker: false)
SCRIPT_ASSET_DIRECTORIES.map do |dir, can_use_s3_cdn, can_use_cdn, for_worker|
next if worker && !for_worker
if can_use_s3_cdn && s3_cdn
s3_cdn + dir
elsif can_use_cdn && cdn
cdn + Discourse.base_path + dir
else
base + dir
end
end.compact
end
def script_src
[
"#{base_url}/logs/",
"#{base_url}/sidekiq/",
"#{base_url}/mini-profiler-resources/",
*script_assets
].tap do |sources|
sources << :report_sample if SiteSetting.content_security_policy_collect_reports
sources << :unsafe_eval if Rails.env.development? # TODO remove this once we have proper source maps in dev
# Support Ember CLI Live reload
if Rails.env.development?
sources << "#{base_url}/ember-cli-live-reload.js"
sources << "#{base_url}/_lr/"
end
# we need analytics.js still as gtag/js is a script wrapper for it
sources << 'https://www.google-analytics.com/analytics.js' if SiteSetting.ga_universal_tracking_code.present?
sources << 'https://www.googletagmanager.com/gtag/js' if SiteSetting.ga_universal_tracking_code.present? && SiteSetting.ga_version == "v4_gtag"
if SiteSetting.gtm_container_id.present?
sources << 'https://www.googletagmanager.com/gtm.js'
sources << "'nonce-#{ApplicationHelper.google_tag_manager_nonce}'"
end
if SiteSetting.splash_screen
sources << "'#{SplashScreenHelper.fingerprint}'"
end
end
end
def worker_src
[
"'self'", # For service worker
*script_assets(worker: true)
]
end
def report_uri
"#{base_url}/csp_reports"
end
def frame_ancestors
[
"'self'",
*EmbeddableHost.pluck(:host).map { |host| "https://#{host}" }
]
end
def restrict_embed?
SiteSetting.content_security_policy_frame_ancestors &&
!SiteSetting.embed_any_origin
end
end
end