diff options
-rw-r--r-- | app/helpers/submodule_helper.rb | 46 | ||||
-rw-r--r-- | changelogs/unreleased/rs-sanitize-submodule-urls.yml | 4 | ||||
-rw-r--r-- | spec/helpers/submodule_helper_spec.rb | 12 |
3 files changed, 46 insertions, 16 deletions
diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb index a762b320d56..b739554a7a4 100644 --- a/app/helpers/submodule_helper.rb +++ b/app/helpers/submodule_helper.rb @@ -1,28 +1,30 @@ module SubmoduleHelper include Gitlab::ShellAdapter + VALID_SUBMODULE_PROTOCOLS = %w[http https git ssh].freeze + # links to files listing for submodule if submodule is a project on this server def submodule_links(submodule_item, ref = nil, repository = @repository) url = repository.submodule_url_for(ref, submodule_item.path) - return url, nil unless url =~ /([^\/:]+)\/([^\/]+(?:\.git)?)\Z/ - - namespace = $1 - project = $2 - project.chomp!('.git') + if url =~ /([^\/:]+)\/([^\/]+(?:\.git)?)\Z/ + namespace, project = $1, $2 + project.sub!(/\.git\z/, '') - if self_url?(url, namespace, project) - return namespace_project_path(namespace, project), - namespace_project_tree_path(namespace, project, - submodule_item.id) - elsif relative_self_url?(url) - relative_self_links(url, submodule_item.id) - elsif github_dot_com_url?(url) - standard_links('github.com', namespace, project, submodule_item.id) - elsif gitlab_dot_com_url?(url) - standard_links('gitlab.com', namespace, project, submodule_item.id) + if self_url?(url, namespace, project) + [namespace_project_path(namespace, project), + namespace_project_tree_path(namespace, project, submodule_item.id)] + elsif relative_self_url?(url) + relative_self_links(url, submodule_item.id) + elsif github_dot_com_url?(url) + standard_links('github.com', namespace, project, submodule_item.id) + elsif gitlab_dot_com_url?(url) + standard_links('gitlab.com', namespace, project, submodule_item.id) + else + [sanitize_submodule_url(url), nil] + end else - return url, nil + [sanitize_submodule_url(url), nil] end end @@ -73,4 +75,16 @@ module SubmoduleHelper namespace_project_tree_path(namespace, base, commit) ] end + + def sanitize_submodule_url(url) + uri = URI.parse(url) + + if uri.scheme.in?(VALID_SUBMODULE_PROTOCOLS) + uri.to_s + else + nil + end + rescue URI::InvalidURIError + nil + end end diff --git a/changelogs/unreleased/rs-sanitize-submodule-urls.yml b/changelogs/unreleased/rs-sanitize-submodule-urls.yml new file mode 100644 index 00000000000..463b3695687 --- /dev/null +++ b/changelogs/unreleased/rs-sanitize-submodule-urls.yml @@ -0,0 +1,4 @@ +--- +title: Sanitize submodule URLs before linking to them in the file tree view +merge_request: +author: diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb index 345bc33a67b..9da33792659 100644 --- a/spec/helpers/submodule_helper_spec.rb +++ b/spec/helpers/submodule_helper_spec.rb @@ -109,6 +109,18 @@ describe SubmoduleHelper do end context 'submodule on unsupported' do + it 'sanitizes unsupported protocols' do + stub_url('javascript:alert("XSS");') + + expect(helper.submodule_links(submodule_item)).to eq([nil, nil]) + end + + it 'sanitizes unsupported protocols disguised as a repository URL' do + stub_url('javascript:alert("XSS");foo/bar.git') + + expect(helper.submodule_links(submodule_item)).to eq([nil, nil]) + end + it 'returns original' do stub_url('http://mygitserver.com/gitlab-org/gitlab-ce') expect(submodule_links(submodule_item)).to eq([repo.submodule_url_for, nil]) |