Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-12-04 19:50:46 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-12-04 19:50:46 +0300
commitf4b6c2668e9c040cbeb2e20aee18a7fb1eea3c5e (patch)
treecea16a86b8ce390299afcd98a58dff8e6efd6826
parentfc3431bef4a527fe0c5bb792e02c3345f4c57d38 (diff)
Add latest changes from gitlab-org/security/gitlab@13-4-stable-ee
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js32
-rw-r--r--app/controllers/explore/projects_controller.rb4
-rw-r--r--app/controllers/search_controller.rb1
-rw-r--r--app/finders/projects_finder.rb4
-rw-r--r--app/graphql/types/user_type.rb8
-rw-r--r--app/models/operations/feature_flags/user_list.rb5
-rw-r--r--app/presenters/user_presenter.rb14
-rw-r--r--app/views/explore/projects/_projects.html.haml8
-rw-r--r--changelogs/unreleased/security-290-graphql-exposed-email.yml5
-rw-r--r--changelogs/unreleased/security-296-private_profile_exposure.yml5
-rw-r--r--changelogs/unreleased/security-idor-ff-user-list.yml5
-rw-r--r--changelogs/unreleased/security-mermaid-rc-13-6.yml5
-rw-r--r--changelogs/unreleased/security-prevent-short-searches-in-explore-projects.yml5
-rw-r--r--changelogs/unreleased/security-search-term-logged.yml5
-rw-r--r--config/application.rb1
-rw-r--r--spec/controllers/search_controller_spec.rb2
-rw-r--r--spec/features/explore/user_explores_projects_spec.rb13
-rw-r--r--spec/features/markdown/mermaid_spec.rb65
-rw-r--r--spec/finders/projects_finder_spec.rb23
-rw-r--r--spec/requests/api/graphql/user_query_spec.rb48
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/C++.gitignore0
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/Java.gitignore0
22 files changed, 240 insertions, 18 deletions
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index cb0e6345059..37a965de86d 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -18,7 +18,13 @@ import { __, sprintf } from '~/locale';
//
// This is an arbitrary number; Can be iterated upon when suitable.
-const MAX_CHAR_LIMIT = 5000;
+const MAX_CHAR_LIMIT = 2000;
+// Max # of mermaid blocks that can be rendered in a page.
+const MAX_MERMAID_BLOCK_LIMIT = 50;
+// Keep a map of mermaid blocks we've already rendered.
+const elsProcessingMap = new WeakMap();
+let renderedMermaidBlocks = 0;
+
let mermaidModule = {};
function importMermaidModule() {
@@ -110,13 +116,22 @@ function renderMermaids($els) {
let renderedChars = 0;
$els.each((i, el) => {
+ // Skipping all the elements which we've already queued in requestIdleCallback
+ if (elsProcessingMap.has(el)) {
+ return;
+ }
+
const { source } = fixElementSource(el);
/**
- * Restrict the rendering to a certain amount of character to
- * prevent mermaidjs from hanging up the entire thread and
- * causing a DoS.
+ * Restrict the rendering to a certain amount of character
+ * and mermaid blocks to prevent mermaidjs from hanging
+ * up the entire thread and causing a DoS.
*/
- if ((source && source.length > MAX_CHAR_LIMIT) || renderedChars > MAX_CHAR_LIMIT) {
+ if (
+ (source && source.length > MAX_CHAR_LIMIT) ||
+ renderedChars > MAX_CHAR_LIMIT ||
+ renderedMermaidBlocks >= MAX_MERMAID_BLOCK_LIMIT
+ ) {
const html = `
<div class="alert gl-alert gl-alert-warning alert-dismissible lazy-render-mermaid-container js-lazy-render-mermaid-container fade show" role="alert">
<div>
@@ -146,8 +161,13 @@ function renderMermaids($els) {
}
renderedChars += source.length;
+ renderedMermaidBlocks += 1;
+
+ const requestId = window.requestIdleCallback(() => {
+ renderMermaidEl(el);
+ });
- renderMermaidEl(el);
+ elsProcessingMap.set(el, requestId);
});
})
.catch(err => {
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index b3fa089a712..1f6f8e44292 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -8,6 +8,8 @@ class Explore::ProjectsController < Explore::ApplicationController
include SortingHelper
include SortingPreference
+ MIN_SEARCH_LENGTH = 3
+
before_action :set_non_archived_param
before_action :set_sorting
@@ -70,7 +72,7 @@ class Explore::ProjectsController < Explore::ApplicationController
def load_projects
load_project_counts
- projects = ProjectsFinder.new(current_user: current_user, params: params).execute
+ projects = ProjectsFinder.new(current_user: current_user, params: params.merge(minimum_search_length: MIN_SEARCH_LENGTH)).execute
projects = preload_associations(projects)
projects = projects.page(params[:page]).without_count
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index dedaf0c903a..d041b2f4b71 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -126,7 +126,6 @@ class SearchController < ApplicationController
payload[:metadata] ||= {}
payload[:metadata]['meta.search.group_id'] = params[:group_id]
payload[:metadata]['meta.search.project_id'] = params[:project_id]
- payload[:metadata]['meta.search.search'] = params[:search]
payload[:metadata]['meta.search.scope'] = params[:scope]
end
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index 471029c1ef9..c3a7301aff6 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -18,6 +18,7 @@
# personal: boolean
# search: string
# search_namespaces: boolean
+# minimum_search_length: int
# non_archived: boolean
# archived: 'only' or boolean
# min_access_level: integer
@@ -177,6 +178,9 @@ class ProjectsFinder < UnionFinder
def by_search(items)
params[:search] ||= params[:name]
+
+ return items.none if params[:search].present? && params[:minimum_search_length].present? && params[:search].length < params[:minimum_search_length].to_i
+
items.optionally_search(params[:search], include_namespace: params[:search_namespaces].present?)
end
diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb
index 8047708776d..4fa62c49611 100644
--- a/app/graphql/types/user_type.rb
+++ b/app/graphql/types/user_type.rb
@@ -19,7 +19,7 @@ module Types
field :state, Types::UserStateEnum, null: false,
description: 'State of the user'
field :email, GraphQL::STRING_TYPE, null: true,
- description: 'User email'
+ description: 'User email', method: :public_email
field :avatar_url, GraphQL::STRING_TYPE, null: true,
description: "URL of the user's avatar"
field :web_url, GraphQL::STRING_TYPE, null: false,
@@ -30,13 +30,11 @@ module Types
resolver: Resolvers::TodoResolver,
description: 'Todos of the user'
field :group_memberships, Types::GroupMemberType.connection_type, null: true,
- description: 'Group memberships of the user',
- method: :group_members
+ description: 'Group memberships of the user'
field :status, Types::UserStatusType, null: true,
description: 'User status'
field :project_memberships, Types::ProjectMemberType.connection_type, null: true,
- description: 'Project memberships of the user',
- method: :project_members
+ description: 'Project memberships of the user'
field :starred_projects, Types::ProjectType.connection_type, null: true,
description: 'Projects starred by the user',
resolver: Resolvers::UserStarredProjectsResolver
diff --git a/app/models/operations/feature_flags/user_list.rb b/app/models/operations/feature_flags/user_list.rb
index b9bdcb59d5f..75a457567ad 100644
--- a/app/models/operations/feature_flags/user_list.rb
+++ b/app/models/operations/feature_flags/user_list.rb
@@ -23,6 +23,11 @@ module Operations
before_destroy :ensure_no_associated_strategies
+ def self.belongs_to?(project_id, user_list_ids)
+ uniq_ids = user_list_ids.uniq
+ where(id: uniq_ids, project_id: project_id).count == uniq_ids.count
+ end
+
private
def ensure_no_associated_strategies
diff --git a/app/presenters/user_presenter.rb b/app/presenters/user_presenter.rb
index f201b36346f..0028e6d9ef0 100644
--- a/app/presenters/user_presenter.rb
+++ b/app/presenters/user_presenter.rb
@@ -2,4 +2,18 @@
class UserPresenter < Gitlab::View::Presenter::Delegated
presents :user
+
+ def group_memberships
+ should_be_private? ? GroupMember.none : user.group_members
+ end
+
+ def project_memberships
+ should_be_private? ? ProjectMember.none : user.project_members
+ end
+
+ private
+
+ def should_be_private?
+ !can?(current_user, :read_user_profile, user)
+ end
end
diff --git a/app/views/explore/projects/_projects.html.haml b/app/views/explore/projects/_projects.html.haml
index d819c4ea554..9b873144112 100644
--- a/app/views/explore/projects/_projects.html.haml
+++ b/app/views/explore/projects/_projects.html.haml
@@ -1,2 +1,6 @@
-- is_explore_page = defined?(explore_page) && explore_page
-= render 'shared/projects/list', projects: projects, user: current_user, explore_page: is_explore_page, pipeline_status: Feature.enabled?(:dashboard_pipeline_status, default_enabled: true)
+- if params[:name].present? && params[:name].size < Explore::ProjectsController::MIN_SEARCH_LENGTH
+ .nothing-here-block
+ %h5= _('Enter at least three characters to search')
+- else
+ - is_explore_page = defined?(explore_page) && explore_page
+ = render 'shared/projects/list', projects: projects, user: current_user, explore_page: is_explore_page, pipeline_status: Feature.enabled?(:dashboard_pipeline_status, default_enabled: true)
diff --git a/changelogs/unreleased/security-290-graphql-exposed-email.yml b/changelogs/unreleased/security-290-graphql-exposed-email.yml
new file mode 100644
index 00000000000..8b07bb1342f
--- /dev/null
+++ b/changelogs/unreleased/security-290-graphql-exposed-email.yml
@@ -0,0 +1,5 @@
+---
+title: 'GraphQL User: do not expose email if set to private'
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-296-private_profile_exposure.yml b/changelogs/unreleased/security-296-private_profile_exposure.yml
new file mode 100644
index 00000000000..05d98788aed
--- /dev/null
+++ b/changelogs/unreleased/security-296-private_profile_exposure.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure group and project memberships are not leaked via API for users with private profiles
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-idor-ff-user-list.yml b/changelogs/unreleased/security-idor-ff-user-list.yml
new file mode 100644
index 00000000000..6d17f9af11d
--- /dev/null
+++ b/changelogs/unreleased/security-idor-ff-user-list.yml
@@ -0,0 +1,5 @@
+---
+title: Forbid setting a gitlabUserList strategy to a list from another project
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-mermaid-rc-13-6.yml b/changelogs/unreleased/security-mermaid-rc-13-6.yml
new file mode 100644
index 00000000000..10c620de108
--- /dev/null
+++ b/changelogs/unreleased/security-mermaid-rc-13-6.yml
@@ -0,0 +1,5 @@
+---
+title: Fix mermaid resource consumption in GFM fields
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-prevent-short-searches-in-explore-projects.yml b/changelogs/unreleased/security-prevent-short-searches-in-explore-projects.yml
new file mode 100644
index 00000000000..672ccc09a33
--- /dev/null
+++ b/changelogs/unreleased/security-prevent-short-searches-in-explore-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Require at least 3 characters when searching for project in the Explore page
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-search-term-logged.yml b/changelogs/unreleased/security-search-term-logged.yml
new file mode 100644
index 00000000000..c3e9d1862bd
--- /dev/null
+++ b/changelogs/unreleased/security-search-term-logged.yml
@@ -0,0 +1,5 @@
+---
+title: Filter search parameter to prevent data leaks
+merge_request:
+author:
+type: security
diff --git a/config/application.rb b/config/application.rb
index 4d2f3745b52..436bb288c3c 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -135,6 +135,7 @@ module Gitlab
hook
import_url
elasticsearch_url
+ search
otp_attempt
sentry_dsn
trace
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index f244392bbad..1293a1a2188 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -272,7 +272,7 @@ RSpec.describe SearchController do
expect(last_payload[:metadata]['meta.search.group_id']).to eq('123')
expect(last_payload[:metadata]['meta.search.project_id']).to eq('456')
- expect(last_payload[:metadata]['meta.search.search']).to eq('hello world')
+ expect(last_payload[:metadata]).not_to have_key('meta.search.search')
expect(last_payload[:metadata]['meta.search.scope']).to eq('issues')
end
end
diff --git a/spec/features/explore/user_explores_projects_spec.rb b/spec/features/explore/user_explores_projects_spec.rb
index e217638f62b..f11a6d17892 100644
--- a/spec/features/explore/user_explores_projects_spec.rb
+++ b/spec/features/explore/user_explores_projects_spec.rb
@@ -34,6 +34,16 @@ RSpec.describe 'User explores projects' do
before do
sign_in(user)
+
+ stub_feature_flags(project_list_filter_bar: false)
+ end
+
+ shared_examples 'minimum search length' do
+ it 'shows a prompt to enter a longer search term', :js do
+ fill_in 'name', with: 'z'
+
+ expect(page).to have_content('Enter at least three characters to search')
+ end
end
context 'when viewing public projects' do
@@ -42,6 +52,7 @@ RSpec.describe 'User explores projects' do
end
include_examples 'shows public and internal projects'
+ include_examples 'minimum search length'
end
context 'when viewing most starred projects' do
@@ -50,6 +61,7 @@ RSpec.describe 'User explores projects' do
end
include_examples 'shows public and internal projects'
+ include_examples 'minimum search length'
end
context 'when viewing trending projects' do
@@ -62,6 +74,7 @@ RSpec.describe 'User explores projects' do
end
include_examples 'shows public projects'
+ include_examples 'minimum search length'
end
end
end
diff --git a/spec/features/markdown/mermaid_spec.rb b/spec/features/markdown/mermaid_spec.rb
index bdb549326fa..58314a49c4b 100644
--- a/spec/features/markdown/mermaid_spec.rb
+++ b/spec/features/markdown/mermaid_spec.rb
@@ -19,6 +19,9 @@ RSpec.describe 'Mermaid rendering', :js do
visit project_issue_path(project, issue)
+ wait_for_requests
+ wait_for_mermaid
+
%w[A B C D].each do |label|
expect(page).to have_selector('svg text', text: label)
end
@@ -39,6 +42,7 @@ RSpec.describe 'Mermaid rendering', :js do
visit project_issue_path(project, issue)
wait_for_requests
+ wait_for_mermaid
expected = '<text style=""><tspan xml:space="preserve" dy="1em" x="1">Line 1</tspan><tspan xml:space="preserve" dy="1em" x="1">Line 2</tspan></text>'
expect(page.html.scan(expected).count).to be(4)
@@ -65,6 +69,9 @@ RSpec.describe 'Mermaid rendering', :js do
visit project_issue_path(project, issue)
+ wait_for_requests
+ wait_for_mermaid
+
page.within('.description') do
expect(page).to have_selector('svg')
expect(page).to have_selector('pre.mermaid')
@@ -92,6 +99,9 @@ RSpec.describe 'Mermaid rendering', :js do
visit project_issue_path(project, issue)
+ wait_for_requests
+ wait_for_mermaid
+
page.within('.description') do
page.find('summary').click
svg = page.find('svg.mermaid')
@@ -118,6 +128,9 @@ RSpec.describe 'Mermaid rendering', :js do
visit project_issue_path(project, issue)
+ wait_for_requests
+ wait_for_mermaid
+
expect(page).to have_css('svg.mermaid[style*="max-width"][width="100%"]')
end
@@ -147,6 +160,7 @@ RSpec.describe 'Mermaid rendering', :js do
end
wait_for_requests
+ wait_for_mermaid
find('.js-lazy-render-mermaid').click
@@ -156,4 +170,55 @@ RSpec.describe 'Mermaid rendering', :js do
expect(page).not_to have_selector('.js-lazy-render-mermaid-container')
end
end
+
+ it 'does not render more than 50 mermaid blocks', :js, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/234081' } do
+ graph_edges = "A-->B;B-->A;"
+
+ description = <<~MERMAID
+ ```mermaid
+ graph LR
+ #{graph_edges}
+ ```
+ MERMAID
+
+ description *= 51
+
+ project = create(:project, :public)
+
+ issue = create(:issue, project: project, description: description)
+
+ visit project_issue_path(project, issue)
+
+ wait_for_requests
+ wait_for_mermaid
+
+ page.within('.description') do
+ expect(page).to have_selector('svg')
+
+ expect(page).to have_selector('.lazy-alert-shown')
+
+ expect(page).to have_selector('.js-lazy-render-mermaid-container')
+ end
+ end
+end
+
+def wait_for_mermaid
+ run_idle_callback = <<~RUN_IDLE_CALLBACK
+ window.requestIdleCallback(() => {
+ window.__CAPYBARA_IDLE_CALLBACK_EXEC__ = 1;
+ })
+ RUN_IDLE_CALLBACK
+
+ page.evaluate_script(run_idle_callback)
+
+ Timeout.timeout(Capybara.default_max_wait_time) do
+ loop until finished_rendering?
+ end
+end
+
+def finished_rendering?
+ check_idle_callback = <<~CHECK_IDLE_CALLBACK
+ window.__CAPYBARA_IDLE_CALLBACK_EXEC__
+ CHECK_IDLE_CALLBACK
+ page.evaluate_script(check_idle_callback) == 1
end
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 8ae19757c25..de59852590f 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -157,6 +157,29 @@ RSpec.describe ProjectsFinder, :do_not_mock_admin_mode do
it { is_expected.to eq([public_project]) }
end
+ describe 'filter by search with minimum search length' do
+ context 'when search term is shorter than minimum length' do
+ let(:params) { { search: 'C', minimum_search_length: 3 } }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when search term is longer than minimum length' do
+ let(:project) { create(:project, :public, group: group, name: 'test_project') }
+ let(:params) { { search: 'test', minimum_search_length: 3 } }
+
+ it { is_expected.to eq([project]) }
+ end
+
+ context 'when minimum length is invalid' do
+ let(:params) { { search: 'C', minimum_search_length: 'x' } }
+
+ it 'ignores the minimum length param' do
+ is_expected.to eq([public_project])
+ end
+ end
+ end
+
describe 'filter by group name' do
let(:params) { { name: group.name, search_namespaces: true } }
diff --git a/spec/requests/api/graphql/user_query_spec.rb b/spec/requests/api/graphql/user_query_spec.rb
index 2f4dc0a9160..bfd92f6344a 100644
--- a/spec/requests/api/graphql/user_query_spec.rb
+++ b/spec/requests/api/graphql/user_query_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe 'getting user information' do
'webUrl' => presenter.web_url,
'avatarUrl' => presenter.avatar_url,
'status' => presenter.status,
- 'email' => presenter.email
+ 'email' => presenter.public_email
))
end
@@ -210,7 +210,7 @@ RSpec.describe 'getting user information' do
context 'the user is private' do
before do
- user.update(private_profile: true)
+ user.update!(private_profile: true)
post_graphql(query, current_user: current_user)
end
@@ -220,6 +220,50 @@ RSpec.describe 'getting user information' do
it_behaves_like 'a working graphql query'
end
+ context 'we request the groupMemberships' do
+ let_it_be(:membership_a) { create(:group_member, :developer, user: user) }
+ let(:group_memberships) { graphql_data_at(:user, :group_memberships, :nodes) }
+ let(:user_fields) { 'groupMemberships { nodes { id } }' }
+
+ it_behaves_like 'a working graphql query'
+
+ it 'cannot be found' do
+ expect(group_memberships).to be_empty
+ end
+
+ context 'the current user is the user' do
+ let(:current_user) { user }
+
+ it 'can be found' do
+ expect(group_memberships).to include(
+ a_hash_including('id' => global_id_of(membership_a))
+ )
+ end
+ end
+ end
+
+ context 'we request the projectMemberships' do
+ let_it_be(:membership_a) { create(:project_member, user: user) }
+ let(:project_memberships) { graphql_data_at(:user, :project_memberships, :nodes) }
+ let(:user_fields) { 'projectMemberships { nodes { id } }' }
+
+ it_behaves_like 'a working graphql query'
+
+ it 'cannot be found' do
+ expect(project_memberships).to be_empty
+ end
+
+ context 'the current user is the user' do
+ let(:current_user) { user }
+
+ it 'can be found' do
+ expect(project_memberships).to include(
+ a_hash_including('id' => global_id_of(membership_a))
+ )
+ end
+ end
+ end
+
context 'we request the authoredMergeRequests' do
let(:user_fields) { 'authoredMergeRequests { nodes { id } }' }
diff --git a/vendor/gitignore/C++.gitignore b/vendor/gitignore/C++.gitignore
index 259148fa18f..259148fa18f 100755..100644
--- a/vendor/gitignore/C++.gitignore
+++ b/vendor/gitignore/C++.gitignore
diff --git a/vendor/gitignore/Java.gitignore b/vendor/gitignore/Java.gitignore
index a1c2a238a96..a1c2a238a96 100755..100644
--- a/vendor/gitignore/Java.gitignore
+++ b/vendor/gitignore/Java.gitignore