From b56d907a1d9065c3df354007fa00daf30626a478 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 29 Sep 2021 12:52:24 +0000 Subject: Add latest changes from gitlab-org/security/gitlab@14-3-stable-ee --- spec/graphql/types/group_invitation_type_spec.rb | 2 +- spec/graphql/types/project_invitation_type_spec.rb | 2 +- spec/lib/banzai/filter/spaced_link_filter_spec.rb | 10 +++ spec/lib/gitlab/fogbugz_import/importer_spec.rb | 80 ++++++++++++++++------ spec/lib/gitlab/string_regex_marker_spec.rb | 12 +++- spec/requests/api/invitations_spec.rb | 40 +++++++---- 6 files changed, 106 insertions(+), 40 deletions(-) (limited to 'spec') diff --git a/spec/graphql/types/group_invitation_type_spec.rb b/spec/graphql/types/group_invitation_type_spec.rb index dab2d43fc90..9eedc2db81d 100644 --- a/spec/graphql/types/group_invitation_type_spec.rb +++ b/spec/graphql/types/group_invitation_type_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Types::GroupInvitationType do specify { expect(described_class.graphql_name).to eq('GroupInvitation') } - specify { expect(described_class).to require_graphql_authorizations(:read_group) } + specify { expect(described_class).to require_graphql_authorizations(:admin_group) } it 'has the expected fields' do expected_fields = %w[ diff --git a/spec/graphql/types/project_invitation_type_spec.rb b/spec/graphql/types/project_invitation_type_spec.rb index 148a763a5fa..5c0b03c2505 100644 --- a/spec/graphql/types/project_invitation_type_spec.rb +++ b/spec/graphql/types/project_invitation_type_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Types::ProjectInvitationType do specify { expect(described_class.graphql_name).to eq('ProjectInvitation') } - specify { expect(described_class).to require_graphql_authorizations(:read_project) } + specify { expect(described_class).to require_graphql_authorizations(:admin_project) } it 'has the expected fields' do expected_fields = %w[ diff --git a/spec/lib/banzai/filter/spaced_link_filter_spec.rb b/spec/lib/banzai/filter/spaced_link_filter_spec.rb index 2c64657d69d..820ebeb6945 100644 --- a/spec/lib/banzai/filter/spaced_link_filter_spec.rb +++ b/spec/lib/banzai/filter/spaced_link_filter_spec.rb @@ -63,6 +63,16 @@ RSpec.describe Banzai::Filter::SpacedLinkFilter do end end + it 'does not process malicious input' do + Timeout.timeout(10) do + doc = filter('[ (](' * 60_000) + + found_links = doc.css('a') + + expect(found_links.size).to eq(0) + end + end + it 'converts multiple URLs' do link1 = '[first](slug one)' link2 = '[second](http://example.com/slug two)' diff --git a/spec/lib/gitlab/fogbugz_import/importer_spec.rb b/spec/lib/gitlab/fogbugz_import/importer_spec.rb index eb0c4da6ce3..9b58b772d1a 100644 --- a/spec/lib/gitlab/fogbugz_import/importer_spec.rb +++ b/spec/lib/gitlab/fogbugz_import/importer_spec.rb @@ -4,23 +4,11 @@ require 'spec_helper' RSpec.describe Gitlab::FogbugzImport::Importer do let(:project) { create(:project_empty_repo) } - let(:importer) { described_class.new(project) } - let(:repo) do - instance_double(Gitlab::FogbugzImport::Repository, - safe_name: 'vim', - path: 'vim', - raw_data: '') - end - - let(:import_data) { { 'repo' => repo } } - let(:credentials) do - { - 'fb_session' => { - 'uri' => 'https://testing.fogbugz.com', - 'token' => 'token' - } - } - end + let(:fogbugz_project) { { 'ixProject' => project.id, 'sProject' => 'vim' } } + let(:import_data) { { 'repo' => fogbugz_project } } + let(:base_url) { 'https://testing.fogbugz.com' } + let(:token) { 'token' } + let(:credentials) { { 'fb_session' => { 'uri' => base_url, 'token' => token } } } let(:closed_bug) do { @@ -46,18 +34,22 @@ RSpec.describe Gitlab::FogbugzImport::Importer do let(:fogbugz_bugs) { [opened_bug, closed_bug] } + subject(:importer) { described_class.new(project) } + before do project.create_import_data(data: import_data, credentials: credentials) - allow_any_instance_of(::Fogbugz::Interface).to receive(:command).with(:listCategories).and_return([]) - allow_any_instance_of(Gitlab::FogbugzImport::Client).to receive(:cases).and_return(fogbugz_bugs) + + stub_fogbugz('listProjects', projects: { project: [fogbugz_project], count: 1 }) + stub_fogbugz('listCategories', categories: { category: [], count: 0 }) + stub_fogbugz('search', cases: { case: fogbugz_bugs, count: fogbugz_bugs.size }) end it 'imports bugs' do - expect { importer.execute }.to change { Issue.count }.by(2) + expect { subject.execute }.to change { Issue.count }.by(2) end it 'imports opened bugs' do - importer.execute + subject.execute issue = Issue.where(project_id: project.id).find_by_title(opened_bug[:sTitle]) @@ -65,10 +57,54 @@ RSpec.describe Gitlab::FogbugzImport::Importer do end it 'imports closed bugs' do - importer.execute + subject.execute issue = Issue.where(project_id: project.id).find_by_title(closed_bug[:sTitle]) expect(issue.state_id).to eq(Issue.available_states[:closed]) end + + context 'verify url' do + context 'when host is localhost' do + let(:base_url) { 'https://localhost:3000' } + + it 'does not allow localhost requests' do + expect { subject.execute } + .to raise_error( + ::Gitlab::HTTP::BlockedUrlError, + "URL 'https://localhost:3000/api.asp' is blocked: Requests to localhost are not allowed" + ) + end + end + + context 'when host is on local network' do + let(:base_url) { 'http://192.168.0.1' } + + it 'does not allow localhost requests' do + expect { subject.execute } + .to raise_error( + ::Gitlab::HTTP::BlockedUrlError, + "URL 'http://192.168.0.1/api.asp' is blocked: Requests to the local network are not allowed" + ) + end + end + + context 'when host is ftp protocol' do + let(:base_url) { 'ftp://testing' } + + it 'only accept http and https requests' do + expect { subject.execute } + .to raise_error( + HTTParty::UnsupportedURIScheme, + "'ftp://testing/api.asp' Must be HTTP, HTTPS or Generic" + ) + end + end + end + + def stub_fogbugz(command, response) + stub_request(:post, "#{base_url}/api.asp") + .with(body: hash_including({ 'cmd' => command, 'token' => token })) + .to_return(status: 200, body: response.to_xml(root: :response)) + end end diff --git a/spec/lib/gitlab/string_regex_marker_spec.rb b/spec/lib/gitlab/string_regex_marker_spec.rb index a02be83558c..0cbe44eacf4 100644 --- a/spec/lib/gitlab/string_regex_marker_spec.rb +++ b/spec/lib/gitlab/string_regex_marker_spec.rb @@ -23,9 +23,10 @@ RSpec.describe Gitlab::StringRegexMarker do context 'with multiple occurrences' do let(:raw) { %{a d} } let(:rich) { %{a <b> <c> d}.html_safe } + let(:regexp) { /<[a-z]>/ } subject do - described_class.new(raw, rich).mark(/<[a-z]>/) do |text, left:, right:, mode:| + described_class.new(raw, rich).mark(regexp) do |text, left:, right:, mode:| %{#{text}}.html_safe end end @@ -34,6 +35,15 @@ RSpec.describe Gitlab::StringRegexMarker do expect(subject).to eq(%{a <b> <c> d}) expect(subject).to be_html_safe end + + context 'with a Gitlab::UntrustedRegexp' do + let(:regexp) { Gitlab::UntrustedRegexp.new('<[a-z]>') } + + it 'marks the matches' do + expect(subject).to eq(%{a <b> <c> d}) + expect(subject).to be_html_safe + end + end end end end diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb index 76a4548df8a..b23ba0021e0 100644 --- a/spec/requests/api/invitations_spec.rb +++ b/spec/requests/api/invitations_spec.rb @@ -259,22 +259,32 @@ RSpec.describe API::Invitations do let(:route) { get invitations_url(source, stranger) } end - %i[maintainer developer access_requester stranger].each do |type| + context "when authenticated as a maintainer" do + it 'returns 200' do + get invitations_url(source, maintainer) + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + expect(json_response.size).to eq(0) + end + end + + %i[developer access_requester stranger].each do |type| context "when authenticated as a #{type}" do - it 'returns 200' do + it 'returns 403' do user = public_send(type) get invitations_url(source, user) - expect(response).to have_gitlab_http_status(:ok) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.size).to eq(0) + expect(response).to have_gitlab_http_status(:forbidden) end end end it 'avoids N+1 queries' do + invite_member_by_email(source, source_type, email, maintainer) + # Establish baseline get invitations_url(source, maintainer) @@ -282,7 +292,7 @@ RSpec.describe API::Invitations do get invitations_url(source, maintainer) end - invite_member_by_email(source, source_type, email, maintainer) + invite_member_by_email(source, source_type, email2, maintainer) expect do get invitations_url(source, maintainer) @@ -290,7 +300,7 @@ RSpec.describe API::Invitations do end it 'does not find confirmed members' do - get invitations_url(source, developer) + get invitations_url(source, maintainer) expect(response).to have_gitlab_http_status(:ok) expect(response).to include_pagination_headers @@ -300,10 +310,10 @@ RSpec.describe API::Invitations do end it 'finds all members with no query string specified' do - invite_member_by_email(source, source_type, email, developer) - invite_member_by_email(source, source_type, email2, developer) + invite_member_by_email(source, source_type, email, maintainer) + invite_member_by_email(source, source_type, email2, maintainer) - get invitations_url(source, developer), params: { query: '' } + get invitations_url(source, maintainer), params: { query: '' } expect(response).to have_gitlab_http_status(:ok) expect(response).to include_pagination_headers @@ -314,17 +324,17 @@ RSpec.describe API::Invitations do end it 'finds the invitation by invite_email with query string' do - invite_member_by_email(source, source_type, email, developer) - invite_member_by_email(source, source_type, email2, developer) + invite_member_by_email(source, source_type, email, maintainer) + invite_member_by_email(source, source_type, email2, maintainer) - get invitations_url(source, developer), params: { query: email } + get invitations_url(source, maintainer), params: { query: email } expect(response).to have_gitlab_http_status(:ok) expect(response).to include_pagination_headers expect(json_response).to be_an Array expect(json_response.count).to eq(1) expect(json_response.first['invite_email']).to eq(email) - expect(json_response.first['created_by_name']).to eq(developer.name) + expect(json_response.first['created_by_name']).to eq(maintainer.name) expect(json_response.first['user_name']).to eq(nil) end end -- cgit v1.2.1