diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-26 14:37:09 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-26 14:37:20 +0000 |
commit | 25ed7b6ae4712518e96d4719b75dd293c57404a2 (patch) | |
tree | 102e02b15909f27a82b6cf64e7b878f0b201b383 /lib | |
parent | daf5ae5bd439f1f32363d410129d5b9e73fbb539 (diff) | |
download | gitlab-ce-25ed7b6ae4712518e96d4719b75dd293c57404a2.tar.gz |
Add latest changes from gitlab-org/security/gitlab@15-3-stable-ee
Diffstat (limited to 'lib')
-rw-r--r-- | lib/banzai/filter/commit_trailers_filter.rb | 34 | ||||
-rw-r--r-- | lib/banzai/filter/pathological_markdown_filter.rb | 27 | ||||
-rw-r--r-- | lib/banzai/pipeline/plain_markdown_pipeline.rb | 1 | ||||
-rw-r--r-- | lib/gitlab/git/rugged_impl/tree.rb | 9 | ||||
-rw-r--r-- | lib/gitlab/git/tree.rb | 9 | ||||
-rw-r--r-- | lib/gitlab/gitaly_client/commit_service.rb | 8 |
6 files changed, 63 insertions, 25 deletions
diff --git a/lib/banzai/filter/commit_trailers_filter.rb b/lib/banzai/filter/commit_trailers_filter.rb index a615abc1989..817bea42757 100644 --- a/lib/banzai/filter/commit_trailers_filter.rb +++ b/lib/banzai/filter/commit_trailers_filter.rb @@ -17,21 +17,10 @@ module Banzai include ActionView::Helpers::TagHelper include AvatarsHelper - TRAILER_REGEXP = /(?<label>[[:alpha:]-]+-by:)/i.freeze - AUTHOR_REGEXP = /(?<author_name>.+)/.freeze - # Devise.email_regexp wouldn't work here since its designed to match - # against strings that only contains email addresses; the \A and \z - # around the expression will only match if the string being matched - # contains just the email nothing else. - MAIL_REGEXP = /<(?<author_email>[^@\s]+@[^@\s]+)>/.freeze - FILTER_REGEXP = /(?<trailer>^\s*#{TRAILER_REGEXP}\s*#{AUTHOR_REGEXP}\s+#{MAIL_REGEXP}$)/mi.freeze - def call doc.xpath('descendant-or-self::text()').each do |node| content = node.to_html - next unless content.match(FILTER_REGEXP) - html = trailer_filter(content) next if html == content @@ -52,11 +41,24 @@ module Banzai # Returns a String with all trailer lines replaced with links to GitLab # users and mailto links to non GitLab users. All links have `data-trailer` # and `data-user` attributes attached. + # + # The code intentionally avoids using Regex for security and performance + # reasons: https://gitlab.com/gitlab-org/gitlab/-/issues/363734 def trailer_filter(text) - text.gsub(FILTER_REGEXP) do |author_match| - label = $~[:label] - "#{label} #{parse_user($~[:author_name], $~[:author_email], label)}" - end + text.lines.map! do |line| + trailer, rest = line.split(':', 2) + + next line unless trailer.downcase.end_with?('-by') && rest.present? + + chunks = rest.split + author_email = chunks.pop.delete_prefix('<').delete_suffix('>') + next line unless Devise.email_regexp.match(author_email) + + author_name = chunks.join(' ').strip + trailer = "#{trailer.strip}:" + + "#{trailer} #{link_to_user_or_email(author_name, author_email, trailer)}\n" + end.join end # Find a GitLab user using the supplied email and generate @@ -67,7 +69,7 @@ module Banzai # trailer - String trailer used in the commit message # # Returns a String with a link to the user. - def parse_user(name, email, trailer) + def link_to_user_or_email(name, email, trailer) link_to_user User.find_by_any_email(email), name: name, email: email, diff --git a/lib/banzai/filter/pathological_markdown_filter.rb b/lib/banzai/filter/pathological_markdown_filter.rb new file mode 100644 index 00000000000..0f94150c7a1 --- /dev/null +++ b/lib/banzai/filter/pathological_markdown_filter.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Banzai + module Filter + class PathologicalMarkdownFilter < HTML::Pipeline::TextFilter + # It's not necessary for this to be precise - we just need to detect + # when there are a non-trivial number of unclosed image links. + # So we don't really care about code blocks, etc. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/370428 + REGEX = /!\[(?:[^\]])+?!\[/.freeze + DETECTION_MAX = 10 + + def call + count = 0 + + @text.scan(REGEX) do |_match| + count += 1 + break if count > DETECTION_MAX + end + + return @text if count <= DETECTION_MAX + + "_Unable to render markdown - too many unclosed markdown image links detected._" + end + end + end +end diff --git a/lib/banzai/pipeline/plain_markdown_pipeline.rb b/lib/banzai/pipeline/plain_markdown_pipeline.rb index 1da0f72996b..fb6f6e9077d 100644 --- a/lib/banzai/pipeline/plain_markdown_pipeline.rb +++ b/lib/banzai/pipeline/plain_markdown_pipeline.rb @@ -5,6 +5,7 @@ module Banzai class PlainMarkdownPipeline < BasePipeline def self.filters FilterArray[ + Filter::PathologicalMarkdownFilter, Filter::MarkdownPreEscapeFilter, Filter::MarkdownFilter, Filter::MarkdownPostEscapeFilter diff --git a/lib/gitlab/git/rugged_impl/tree.rb b/lib/gitlab/git/rugged_impl/tree.rb index bc0af12d7e3..66cfc02130b 100644 --- a/lib/gitlab/git/rugged_impl/tree.rb +++ b/lib/gitlab/git/rugged_impl/tree.rb @@ -16,9 +16,10 @@ module Gitlab TREE_SORT_ORDER = { tree: 0, blob: 1, commit: 2 }.freeze override :tree_entries - def tree_entries(repository, sha, path, recursive, pagination_params = nil) + def tree_entries(repository, sha, path, recursive, skip_flat_paths, pagination_params = nil) if use_rugged?(repository, :rugged_tree_entries) - entries = execute_rugged_call(:tree_entries_with_flat_path_from_rugged, repository, sha, path, recursive) + entries = execute_rugged_call( + :tree_entries_with_flat_path_from_rugged, repository, sha, path, recursive, skip_flat_paths) if pagination_params paginated_response(entries, pagination_params[:limit], pagination_params[:page_token].to_s) @@ -60,11 +61,11 @@ module Gitlab [result, cursor] end - def tree_entries_with_flat_path_from_rugged(repository, sha, path, recursive) + def tree_entries_with_flat_path_from_rugged(repository, sha, path, recursive, skip_flat_paths) tree_entries_from_rugged(repository, sha, path, recursive).tap do |entries| # This was an optimization to reduce N+1 queries for Gitaly # (https://gitlab.com/gitlab-org/gitaly/issues/530). - rugged_populate_flat_path(repository, sha, path, entries) + rugged_populate_flat_path(repository, sha, path, entries) unless skip_flat_paths end end diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb index eb008507397..f0eef619e13 100644 --- a/lib/gitlab/git/tree.rb +++ b/lib/gitlab/git/tree.rb @@ -15,15 +15,16 @@ module Gitlab # Uses rugged for raw objects # # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/320 - def where(repository, sha, path = nil, recursive = false, pagination_params = nil) + def where(repository, sha, path = nil, recursive = false, skip_flat_paths = true, pagination_params = nil) path = nil if path == '' || path == '/' - tree_entries(repository, sha, path, recursive, pagination_params) + tree_entries(repository, sha, path, recursive, skip_flat_paths, pagination_params) end - def tree_entries(repository, sha, path, recursive, pagination_params = nil) + def tree_entries(repository, sha, path, recursive, skip_flat_paths, pagination_params = nil) wrapped_gitaly_errors do - repository.gitaly_commit_client.tree_entries(repository, sha, path, recursive, pagination_params) + repository.gitaly_commit_client.tree_entries( + repository, sha, path, recursive, skip_flat_paths, pagination_params) end end diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb index 9fb34f74c82..0f306a9825d 100644 --- a/lib/gitlab/gitaly_client/commit_service.rb +++ b/lib/gitlab/gitaly_client/commit_service.rb @@ -5,6 +5,8 @@ module Gitlab class CommitService include Gitlab::EncodingHelper + TREE_ENTRIES_DEFAULT_LIMIT = 100_000 + def initialize(repository) @gitaly_repo = repository.gitaly_repository @repository = repository @@ -111,12 +113,16 @@ module Gitlab nil end - def tree_entries(repository, revision, path, recursive, pagination_params) + def tree_entries(repository, revision, path, recursive, skip_flat_paths, pagination_params) + pagination_params ||= {} + pagination_params[:limit] ||= TREE_ENTRIES_DEFAULT_LIMIT + request = Gitaly::GetTreeEntriesRequest.new( repository: @gitaly_repo, revision: encode_binary(revision), path: path.present? ? encode_binary(path) : '.', recursive: recursive, + skip_flat_paths: skip_flat_paths, pagination_params: pagination_params ) request.sort = Gitaly::GetTreeEntriesRequest::SortBy::TREES_FIRST if pagination_params |