<p><%= t ".local_chapters.list_text" %></p>
<ul>
<% @local_chapters.each do |chapter| %>
- <li><a href="<%= chapter.url %>"><%= t "osm_community_index.communities.#{chapter.id}.name" %></a></li>
+ <li>
+ <% if chapter.url %>
+ <a href="<%= chapter.url %>"><%= t "osm_community_index.communities.#{chapter.id}.name" %></a>
+ <% else %>
+ <%= t "osm_community_index.communities.#{chapter.id}.name" %>
+ <% end %>
+ </li>
<% end %>
</ul>
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
--- /dev/null
+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