discourse/lib/content_security_policy/default.rb
Penar Musaraj 6f76479054
FEATURE: Add upgrade-insecure-requests to CSP when force_https is enabled (#13348)
If force_https is enabled all resource (including markdown preview and so on) will be accessed using HTTPS

If for any reason you attempt to link to non HTTPS reachable content content may appear broken
2021-06-10 10:53:10 +10:00

103 lines
3.3 KiB
Ruby

# frozen_string_literal: true
require_dependency '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] = [:none]
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
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