gem "dalli"
gem "kgio"
-# Load secure_headers for Content-Security-Policy support
-gem "secure_headers"
-
# Load canonical-rails to generate canonical URLs
gem "canonical-rails"
sass-embedded (1.64.2)
google-protobuf (~> 3.23)
rake (>= 13.0.0)
- secure_headers (6.5.0)
selenium-webdriver (4.21.1)
base64 (~> 0.2)
rexml (~> 3.2, >= 3.2.5)
rubocop-rake
sanitize
sass-embedded (~> 1.64.0)
- secure_headers
selenium-webdriver
simplecov
simplecov-lcov
before_action :check_database_readable
before_action :check_database_writable, :only => [:update]
- before_action :allow_thirdparty_images, :only => [:edit, :update]
+
+ allow_thirdparty_images :only => [:edit, :update]
+ allow_social_login :only => [:edit, :update]
def edit
@tokens = current_user.oauth_tokens.authorized
- append_content_security_policy_directives(
- :form_action => %w[accounts.google.com *.facebook.com login.microsoftonline.com github.com meta.wikimedia.org]
- )
-
if errors = session.delete(:user_errors)
errors.each do |attribute, error|
current_user.errors.add(attribute, error)
def update
@tokens = current_user.oauth_tokens.authorized
- append_content_security_policy_directives(
- :form_action => %w[accounts.google.com *.facebook.com login.microsoftonline.com github.com meta.wikimedia.org]
- )
-
user_params = params.require(:user).permit(:display_name, :new_email, :pass_crypt, :pass_crypt_confirmation, :auth_provider)
if params[:user][:auth_provider].blank? ||
rescue_from RailsParam::InvalidParameterError, :with => :invalid_parameter
before_action :fetch_body
- around_action :better_errors_allow_inline, :if => proc { Rails.env.development? }
attr_accessor :current_user, :oauth_token
helper_method :current_user
helper_method :oauth_token
+ def self.allow_thirdparty_images(**options)
+ content_security_policy(options) do |policy|
+ policy.img_src("*")
+ end
+ end
+
+ def self.allow_social_login(**options)
+ content_security_policy(options) do |policy|
+ policy.form_action(*policy.form_action, "accounts.google.com", "*.facebook.com", "login.microsoftonline.com", "github.com", "meta.wikimedia.org")
+ end
+ end
+
+ def self.allow_all_form_action(**options)
+ content_security_policy(options) do |policy|
+ policy.form_action(nil)
+ end
+ end
+
private
def authorize_web
end
def map_layout
- append_content_security_policy_directives(
- :child_src => %w[http://127.0.0.1:8111 https://127.0.0.1:8112],
- :frame_src => %w[http://127.0.0.1:8111 https://127.0.0.1:8112],
- :connect_src => [Settings.nominatim_url, Settings.overpass_url, Settings.fossgis_osrm_url, Settings.graphhopper_url, Settings.fossgis_valhalla_url],
- :form_action => %w[render.openstreetmap.org],
- :style_src => %w['unsafe-inline']
- )
+ policy = request.content_security_policy.clone
+
+ policy.child_src(*policy.child_src, "http://127.0.0.1:8111", "https://127.0.0.1:8112")
+ policy.frame_src(*policy.frame_src, "http://127.0.0.1:8111", "https://127.0.0.1:8112")
+ policy.connect_src(*policy.connect_src, Settings.nominatim_url, Settings.overpass_url, Settings.fossgis_osrm_url, Settings.graphhopper_url, Settings.fossgis_valhalla_url)
+ policy.form_action(*policy.form_action, "render.openstreetmap.org")
+ policy.style_src(*policy.style_src, :unsafe_inline)
+
+ request.content_security_policy = policy
case Settings.status
when "database_offline", "api_offline"
request.xhr? ? "xhr" : "map"
end
- def allow_thirdparty_images
- append_content_security_policy_directives(:img_src => %w[*])
- end
-
def preferred_editor
if params[:editor]
params[:editor]
end
end
- def better_errors_allow_inline
- yield
- rescue StandardError
- append_content_security_policy_directives(
- :script_src => %w['unsafe-inline'],
- :style_src => %w['unsafe-inline']
- )
-
- raise
- end
-
def current_ability
Ability.new(current_user)
end
before_action :lookup_user, :only => [:show, :comments]
before_action :check_database_writable, :only => [:new, :create, :edit, :update, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
- before_action :allow_thirdparty_images, :only => [:new, :create, :edit, :update, :index, :show, :comments]
+
+ allow_thirdparty_images :only => [:new, :create, :edit, :update, :index, :show, :comments]
def index
if params[:display_name]
before_action :update_totp, :only => [:finish]
authorize_resource :class => false
+ content_security_policy(:only => :embed) do |policy|
+ policy.frame_ancestors("*")
+ end
+
caches_page :embed
# When the user clicks 'Export' we redirect to a URL which generates the export download
end
end
- def embed
- append_content_security_policy_directives(
- :frame_ancestors => %w[*]
- )
- end
+ def embed; end
end
before_action :lookup_user, :only => [:new, :create]
before_action :check_database_readable
before_action :check_database_writable, :only => [:new, :create, :reply, :mark, :destroy]
- before_action :allow_thirdparty_images, :only => [:new, :create, :show]
+
+ allow_thirdparty_images :only => [:new, :create, :show]
# Show a message
def show
prepend_before_action :authorize_web
before_action :set_locale
- before_action :allow_all_form_action, :only => [:new]
- authorize_resource :class => false
-
- private
+ allow_all_form_action :only => :new
- def allow_all_form_action
- override_content_security_policy_directives(:form_action => []) if Settings.csp_enforce || Settings.key?(:csp_report_url)
- end
+ authorize_resource :class => false
end
layout "site"
+ allow_all_form_action :only => :oauth1_authorize
+
def revoke
@token = current_user.oauth_tokens.find_by :token => params[:token]
if @token
end
def oauth1_authorize
- override_content_security_policy_directives(:form_action => []) if Settings.csp_enforce || Settings.key?(:csp_report_url)
-
if @token.invalidated?
@message = t "oauth.authorize_failure.invalid"
render :action => "authorize_failure"
authorize_resource :class => false
- def new
- override_content_security_policy_directives(:form_action => []) if Settings.csp_enforce || Settings.key?(:csp_report_url)
+ allow_all_form_action :only => :new
+ def new
referer = safe_referer(params[:referer]) if params[:referer]
parse_oauth_referer referer
authorize_resource :class => false
+ content_security_policy(:only => :edit) do |policy|
+ policy.frame_src(*policy.frame_src, :blob)
+ end
+
+ content_security_policy(:only => :id) do |policy|
+ policy.connect_src("*")
+ policy.img_src("*", :blob)
+ policy.script_src(*policy.script_src, "dev.virtualearth.net", :unsafe_eval)
+ policy.style_src(*policy.style_src, :unsafe_inline)
+ end
+
def index
session[:location] ||= OSM.ip_location(request.env["REMOTE_ADDR"]) unless Settings.status == "database_readonly" || Settings.status == "database_offline"
end
require_user
end
- if %w[id].include?(editor)
- append_content_security_policy_directives(
- :frame_src => %w[blob:]
- )
- end
-
begin
if params[:node]
bbox = Node.visible.find(params[:node]).bbox.to_unscaled
end
def id
- append_content_security_policy_directives(
- :connect_src => %w[*],
- :img_src => %w[* blob:],
- :script_src => %w[dev.virtualearth.net 'unsafe-eval'],
- :style_src => %w['unsafe-inline']
- )
-
render :layout => false
end
before_action :check_database_writable, :only => [:new, :go_public]
before_action :require_cookies, :only => [:new]
before_action :lookup_user_by_name, :only => [:set_status, :destroy]
- before_action :allow_thirdparty_images, :only => [:show]
+
+ allow_thirdparty_images :only => :show
+ allow_social_login :only => :new
##
# display a list of users matching specified criteria
parse_oauth_referer @referer
- append_content_security_policy_directives(
- :form_action => %w[accounts.google.com *.facebook.com login.microsoftonline.com github.com meta.wikimedia.org]
- )
-
if current_user
# The user is logged in already, so don't show them the signup
# page, instead send them to the home page
<%= yield :head %>
<%= yield :auto_discovery_link_tag %>
<%= csrf_meta_tag %>
- <meta name="csp-nonce" content="<%= content_security_policy_style_nonce %>" />
+ <%= csp_meta_tag %>
<title><%= "#{@title} | " if @title %><%= t "layouts.project_name.title" %></title>
<% end %>
# See the Securing Rails Applications Guide for more information:
# https://guides.rubyonrails.org/security.html#content-security-policy-header
-# Rails.application.configure do
-# config.content_security_policy do |policy|
-# policy.default_src :self, :https
-# policy.font_src :self, :https, :data
-# policy.img_src :self, :https, :data
-# policy.object_src :none
-# policy.script_src :self, :https
-# policy.style_src :self, :https
-# # Specify URI for violation reports
-# # policy.report_uri "/csp-violation-report-endpoint"
-# 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
+Rails.application.configure do
+ connect_src = [:self]
+ img_src = [:self, :data, "www.gravatar.com", "*.wp.com", "tile.openstreetmap.org", "*.tile.thunderforest.com", "tile.tracestrack.com", "*.openstreetmap.fr"]
+ script_src = [:self]
+
+ connect_src << Settings.matomo["location"] if defined?(Settings.matomo)
+ img_src << Settings.matomo["location"] if defined?(Settings.matomo)
+ script_src << Settings.matomo["location"] if defined?(Settings.matomo)
+
+ img_src << Settings.avatar_storage_url if Settings.key?(:avatar_storage_url)
+ img_src << Settings.trace_image_storage_url if Settings.key?(:trace_image_storage_url)
+
+ config.content_security_policy do |policy|
+ policy.default_src :self
+ policy.child_src(:self)
+ policy.connect_src(*connect_src)
+ policy.font_src(:none)
+ policy.form_action(:self)
+ policy.frame_ancestors(:self)
+ policy.frame_src(:self)
+ policy.img_src(*img_src)
+ policy.manifest_src(:self)
+ policy.media_src(:none)
+ policy.object_src(:self)
+ policy.plugin_types
+ policy.script_src(*script_src)
+ policy.style_src(:self)
+ policy.worker_src(:none)
+ policy.manifest_src(:self)
+ policy.report_uri(Settings.csp_report_url) if Settings.key?(:csp_report_url)
+ end
+
+ # Generate session nonces for permitted importmap and inline scripts
+ config.content_security_policy_nonce_generator = ->(_request) { SecureRandom.base64(24) }
+ config.content_security_policy_nonce_directives = %w[style-src]
+
+ # Report violations without enforcing the policy.
+ config.content_security_policy_report_only = true unless Settings.csp_enforce
+end
+++ /dev/null
-csp_policy = {
- :preserve_schemes => true,
- :default_src => %w['self'],
- :child_src => %w['self'],
- :connect_src => %w['self'],
- :font_src => %w['none'],
- :form_action => %w['self'],
- :frame_ancestors => %w['self'],
- :frame_src => %w['self'],
- :img_src => %w['self' data: www.gravatar.com *.wp.com tile.openstreetmap.org *.tile.openstreetmap.org *.tile.thunderforest.com tile.tracestrack.com *.openstreetmap.fr],
- :manifest_src => %w['self'],
- :media_src => %w['none'],
- :object_src => %w['self'],
- :plugin_types => %w[],
- :script_src => %w['self'],
- :style_src => %w['self'],
- :worker_src => %w['none'],
- :report_uri => []
-}
-
-csp_policy[:connect_src] << Settings.matomo["location"] if defined?(Settings.matomo)
-csp_policy[:img_src] << Settings.matomo["location"] if defined?(Settings.matomo)
-csp_policy[:script_src] << Settings.matomo["location"] if defined?(Settings.matomo)
-
-csp_policy[:img_src] << Settings.avatar_storage_url if Settings.key?(:avatar_storage_url)
-csp_policy[:img_src] << Settings.trace_image_storage_url if Settings.key?(:trace_image_storage_url)
-
-csp_policy[:report_uri] << Settings.csp_report_url if Settings.key?(:csp_report_url)
-
-cookie_policy = {
- :httponly => { :only => %w[_osm_session _osm_totp_token] }
-}
-
-SecureHeaders::Configuration.default do |config|
- config.hsts = SecureHeaders::OPT_OUT
- config.referrer_policy = "strict-origin-when-cross-origin"
-
- if Settings.csp_enforce
- config.csp = csp_policy
- config.csp_report_only = SecureHeaders::OPT_OUT
- elsif Settings.key?(:csp_report_url)
- config.csp = SecureHeaders::OPT_OUT
- config.csp_report_only = csp_policy
- else
- config.csp = SecureHeaders::OPT_OUT
- config.csp_report_only = SecureHeaders::OPT_OUT
- end
-
- config.cookies = cookie_policy
-end
# Be sure to restart your server when you modify this file.
if Settings.key?(:memcache_servers)
- Rails.application.config.session_store :mem_cache_store, :memcache_server => Settings.memcache_servers, :namespace => "rails:session", :key => "_osm_session"
+ Rails.application.config.session_store :mem_cache_store, :memcache_server => Settings.memcache_servers, :namespace => "rails:session", :key => "_osm_session", :same_site => :lax
else
- Rails.application.config.session_store :cache_store, :key => "_osm_session", :cache => ActiveSupport::Cache::MemoryStore.new
+ Rails.application.config.session_store :cache_store, :key => "_osm_session", :cache => ActiveSupport::Cache::MemoryStore.new, :same_site => :lax
end