103 lines
4.6 KiB
Ruby
103 lines
4.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Be sure to restart your server when you modify this file.
|
|
|
|
# Define an application-wide content security policy.
|
|
# See the Securing Rails Applications Guide for more information:
|
|
# https://guides.rubyonrails.org/security.html#content-security-policy-header
|
|
|
|
require_relative 'sentry_csp'
|
|
require_relative 'sentry_javascript'
|
|
|
|
module CSP
|
|
def self.apply_yml_settings_for(policy)
|
|
csp_settings = CodeOcean::Config.new(:content_security_policy)
|
|
|
|
csp_settings.read.each do |directive, additional_settings|
|
|
add_policy(policy, directive, additional_settings)
|
|
end
|
|
end
|
|
|
|
def self.apply_sentry_settings_for(policy)
|
|
sentry_host_source = get_host_source(SentryJavascript.dsn)
|
|
add_policy(policy, :connect_src, [sentry_host_source])
|
|
end
|
|
|
|
def self.add_policy(policy, directive, additional_settings)
|
|
all_settings = additional_settings
|
|
existing_settings = if directive == 'report_uri'
|
|
''
|
|
else
|
|
policy.public_send(directive) || []
|
|
end
|
|
all_settings += existing_settings unless existing_settings == ["'none'"]
|
|
all_settings.uniq! unless directive == 'report_uri'
|
|
policy.public_send(directive, *all_settings)
|
|
end
|
|
private_class_method :add_policy
|
|
|
|
def self.get_host_source(url)
|
|
uri = URI.parse(url)
|
|
"#{uri.scheme}://#{uri.host}"
|
|
end
|
|
private_class_method :get_host_source
|
|
end
|
|
|
|
Rails.application.configure do
|
|
config.content_security_policy do |policy|
|
|
policy.default_src :none
|
|
policy.base_uri :self
|
|
policy.font_src :self
|
|
# Code executions might return a base64 encoded image as a :data URI
|
|
policy.img_src :self, :data
|
|
policy.object_src :none
|
|
policy.media_src :self
|
|
policy.script_src_elem :self, :report_sample
|
|
policy.script_src_attr :none
|
|
# The `script_src` directive is only a fallback for browsers not supporting `script_src_elem` and `script_src_attr`.
|
|
policy.script_src :self, :report_sample
|
|
# Some dependencies add new styles to the DOM dynamically, requiring :unsafe-inline.
|
|
# Currently, these include turbolinks, and vis.js.
|
|
policy.style_src_elem :self, :unsafe_inline, :report_sample
|
|
# We still use some inline styles within the application, and indirectly through d3.js.
|
|
# Further, the ToastUi markdown editor currently requires inline styles, too.
|
|
policy.style_src_attr :unsafe_inline, :report_sample
|
|
# The `style_src` directive is only a fallback for browsers not supporting `style_src_elem` and `style_src_attr`.
|
|
policy.style_src :self, :unsafe_inline, :report_sample
|
|
policy.connect_src :self
|
|
# Web workers are used by the ACE editor (for syntax highlighting) and JStree (for processing trees).
|
|
# Those dependencies are loading further code via blobs.
|
|
policy.worker_src :self, :blob
|
|
# The `child_src` directive is only a fallback for browsers not supporting `worker_src`.
|
|
policy.child_src :self, :blob
|
|
policy.form_action :self
|
|
policy.frame_ancestors :self, 'https://*.htwk-leipzig.de'
|
|
policy.frame_src :none
|
|
policy.manifest_src :none
|
|
|
|
# Trusted Types are not yet added to the application, thus we cannot enforce them.
|
|
# policy.require_trusted_types_for :script
|
|
# policy.trusted_types 'example'
|
|
|
|
# Specify URI for violation reports
|
|
policy.report_uri SentryCsp.report_url if SentryCsp.active?
|
|
|
|
# We want to apply a default sandbox to our page, just allowing a few features.
|
|
# These values also apply to popups rendering user code with the `render_host`.
|
|
# Thus, rendered pages still miss some features, e.g., `allow-popups-to-escape-sandbox`, `allow-top-navigation`
|
|
# Despite restricting the sandbox as much as possible, Chrome warns:
|
|
# "An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing."
|
|
policy.sandbox 'allow-downloads', 'allow-forms', 'allow-modals', 'allow-popups', 'allow-same-origin', 'allow-scripts'
|
|
|
|
CSP.apply_yml_settings_for policy
|
|
CSP.apply_sentry_settings_for policy if SentryJavascript.active?
|
|
end
|
|
|
|
# Generate session nonces for permitted importmap, inline scripts, and inline styles.
|
|
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
|
|
# config.content_security_policy_nonce_directives = %w[script-src style-src]
|
|
|
|
# Report violations without enforcing the policy.
|
|
# config.content_security_policy_report_only = true
|
|
end
|