From af6fec502ac22d68224ec80bc925781955b0e842 Mon Sep 17 00:00:00 2001 From: Andy Allan Date: Wed, 2 Nov 2022 18:21:00 +0000 Subject: [PATCH] Validate URLs against supply-chain attacks Unfortunately validates_url gem doesn't support mailto or xmpp urls, so we need to write our own validation. --- app/views/site/communities.html.erb | 8 ++++++- lib/osm_community_index/resource_backend.rb | 23 +++++++++++++++++++ .../resource_backend_test.rb | 15 ++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 test/lib/osm_community_index/resource_backend_test.rb diff --git a/app/views/site/communities.html.erb b/app/views/site/communities.html.erb index ba687966f..c21406683 100644 --- a/app/views/site/communities.html.erb +++ b/app/views/site/communities.html.erb @@ -9,7 +9,13 @@

<%= t ".local_chapters.list_text" %>

diff --git a/lib/osm_community_index/resource_backend.rb b/lib/osm_community_index/resource_backend.rb index e16d951a4..3ed14e6de 100644 --- a/lib/osm_community_index/resource_backend.rb +++ b/lib/osm_community_index/resource_backend.rb @@ -8,7 +8,30 @@ module OsmCommunityIndex def self.load(file_path) resources = JSON.parse(File.read(file_path)) + resources["resources"].values.map! do |v| + v["strings"]["url"] = nil unless valid_url? v["strings"]["url"] + end resources["resources"].values end + + # This is to avoid any problems if upstream contains urls with `script:` or + # similar schemes, i.e. to guard against supply-chain attacks. + # Unfortunately the validates_url gem doesn't support `mailto:` or similar + # urls. This method is based on their approach to validation. + def self.valid_url?(url) + return true if url.nil? + + schemes = %w[http https mailto xmpp] + uri = URI.parse(url) + scheme = uri&.scheme + + valid_raw_url = scheme && url =~ /\A#{URI::DEFAULT_PARSER.make_regexp([scheme])}\z/ + valid_scheme = scheme && schemes.include?(scheme) + return true if valid_raw_url && valid_scheme + + false + rescue URI::InvalidURIError, URI::InvalidComponentError + false + end end end diff --git a/test/lib/osm_community_index/resource_backend_test.rb b/test/lib/osm_community_index/resource_backend_test.rb new file mode 100644 index 000000000..91b0bb5ae --- /dev/null +++ b/test/lib/osm_community_index/resource_backend_test.rb @@ -0,0 +1,15 @@ +require "test_helper" + +class ResourceBackendTest < ActiveSupport::TestCase + def test_valid_url + klass = OsmCommunityIndex::ResourceBackend + + assert klass.valid_url?(nil) + assert klass.valid_url?("http://example.com") + assert klass.valid_url?("mailto:bob@example.com?subject=Foo%20Bar") + assert klass.valid_url?("xmpp:osm@jabber.example.org?join") + + assert_not klass.valid_url?("javascript:doSomething()") + assert_not klass.valid_url?("foo:[]") + end +end -- 2.43.2