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
path: root/spec/lib
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib')
-rw-r--r--spec/lib/banzai/filter/label_reference_filter_spec.rb7
-rw-r--r--spec/lib/banzai/filter/reference_redactor_filter_spec.rb64
-rw-r--r--spec/lib/gitlab/auth_spec.rb41
-rw-r--r--spec/lib/gitlab/gfm/uploads_rewriter_spec.rb10
-rw-r--r--spec/lib/gitlab/hotlinking_detector_spec.rb75
-rw-r--r--spec/lib/gitlab/import_export/attribute_cleaner_spec.rb3
-rw-r--r--spec/lib/gitlab/regex_spec.rb32
-rw-r--r--spec/lib/uploaded_file_spec.rb10
8 files changed, 227 insertions, 15 deletions
diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb
index 5a672de13d7..de7a70db1ac 100644
--- a/spec/lib/banzai/filter/label_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb
@@ -523,7 +523,12 @@ describe Banzai::Filter::LabelReferenceFilter do
end
context 'when group name has HTML entities' do
- let(:another_group) { create(:group, name: '<img src=x onerror=alert(1)>', path: 'another_group') }
+ let(:another_group) { create(:group, name: 'random', path: 'another_group') }
+
+ before do
+ another_group.name = "<img src=x onerror=alert(1)>"
+ another_group.save!(validate: false)
+ end
it 'escapes the HTML entities' do
expect(result.text)
diff --git a/spec/lib/banzai/filter/reference_redactor_filter_spec.rb b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb
index 9739afd3d57..a68581b3000 100644
--- a/spec/lib/banzai/filter/reference_redactor_filter_spec.rb
+++ b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb
@@ -20,8 +20,8 @@ describe Banzai::Filter::ReferenceRedactorFilter do
it 'skips when the skip_redaction flag is set' do
user = create(:user)
project = create(:project)
-
link = reference_link(project: project.id, reference_type: 'test')
+
doc = filter(link, current_user: user, skip_redaction: true)
expect(doc.css('a').length).to eq 1
@@ -51,8 +51,8 @@ describe Banzai::Filter::ReferenceRedactorFilter do
user = create(:user)
project = create(:project)
project.add_maintainer(user)
-
link = reference_link(project: project.id, reference_type: 'test')
+
doc = filter(link, current_user: user)
expect(doc.css('a').length).to eq 1
@@ -69,8 +69,8 @@ describe Banzai::Filter::ReferenceRedactorFilter do
it 'removes unpermitted references' do
user = create(:user)
project = create(:project)
-
link = reference_link(project: project.id, reference_type: 'test')
+
doc = filter(link, current_user: user)
expect(doc.css('a').length).to eq 0
@@ -90,8 +90,8 @@ describe Banzai::Filter::ReferenceRedactorFilter do
non_member = create(:user)
project = create(:project, :public)
issue = create(:issue, :confidential, project: project)
-
link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
+
doc = filter(link, current_user: non_member)
expect(doc.css('a').length).to eq 0
@@ -124,8 +124,8 @@ describe Banzai::Filter::ReferenceRedactorFilter do
assignee = create(:user)
project = create(:project, :public)
issue = create(:issue, :confidential, project: project, assignees: [assignee])
-
link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
+
doc = filter(link, current_user: assignee)
expect(doc.css('a').length).to eq 1
@@ -136,8 +136,8 @@ describe Banzai::Filter::ReferenceRedactorFilter do
project = create(:project, :public)
project.add_developer(member)
issue = create(:issue, :confidential, project: project)
-
link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
+
doc = filter(link, current_user: member)
expect(doc.css('a').length).to eq 1
@@ -147,20 +147,62 @@ describe Banzai::Filter::ReferenceRedactorFilter do
admin = create(:admin)
project = create(:project, :public)
issue = create(:issue, :confidential, project: project)
-
link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
+
doc = filter(link, current_user: admin)
expect(doc.css('a').length).to eq 1
end
+
+ context "when a confidential issue is moved from a public project to a private one" do
+ let(:public_project) { create(:project, :public) }
+ let(:private_project) { create(:project, :private) }
+
+ it 'removes references for author' do
+ author = create(:user)
+ issue = create(:issue, :confidential, project: public_project, author: author)
+ issue.update!(project: private_project) # move issue to private project
+ link = reference_link(project: private_project.id, issue: issue.id, reference_type: 'issue')
+
+ doc = filter(link, current_user: author)
+
+ expect(doc.css('a').length).to eq 0
+ end
+
+ it 'removes references for assignee' do
+ assignee = create(:user)
+ issue = create(:issue, :confidential, project: public_project, assignees: [assignee])
+ issue.update!(project: private_project) # move issue to private project
+ link = reference_link(project: private_project.id, issue: issue.id, reference_type: 'issue')
+
+ doc = filter(link, current_user: assignee)
+
+ expect(doc.css('a').length).to eq 0
+ end
+
+ it 'allows references for project members' do
+ member = create(:user)
+ project = create(:project, :public)
+ project_2 = create(:project, :private)
+ project.add_developer(member)
+ project_2.add_developer(member)
+ issue = create(:issue, :confidential, project: project)
+ issue.update!(project: project_2) # move issue to private project
+ link = reference_link(project: project_2.id, issue: issue.id, reference_type: 'issue')
+
+ doc = filter(link, current_user: member)
+
+ expect(doc.css('a').length).to eq 1
+ end
+ end
end
it 'allows references for non confidential issues' do
user = create(:user)
project = create(:project, :public)
issue = create(:issue, project: project)
-
link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
+
doc = filter(link, current_user: user)
expect(doc.css('a').length).to eq 1
@@ -172,8 +214,8 @@ describe Banzai::Filter::ReferenceRedactorFilter do
it 'removes unpermitted Group references' do
user = create(:user)
group = create(:group, :private)
-
link = reference_link(group: group.id, reference_type: 'user')
+
doc = filter(link, current_user: user)
expect(doc.css('a').length).to eq 0
@@ -183,8 +225,8 @@ describe Banzai::Filter::ReferenceRedactorFilter do
user = create(:user)
group = create(:group, :private)
group.add_developer(user)
-
link = reference_link(group: group.id, reference_type: 'user')
+
doc = filter(link, current_user: user)
expect(doc.css('a').length).to eq 1
@@ -200,8 +242,8 @@ describe Banzai::Filter::ReferenceRedactorFilter do
context 'with data-user' do
it 'allows any User reference' do
user = create(:user)
-
link = reference_link(user: user.id, reference_type: 'user')
+
doc = filter(link)
expect(doc.css('a').length).to eq 1
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index e0c1f830165..528019bb9ff 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -164,6 +164,12 @@ describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
expect(subject).to eq(Gitlab::Auth::Result.new(build.user, build.project, :build, described_class.build_authentication_abilities))
end
+
+ it 'fails with blocked user token' do
+ build.update(user: create(:user, :blocked))
+
+ expect(subject).to eq(Gitlab::Auth::Result.new(nil, nil, nil, nil))
+ end
end
(HasStatus::AVAILABLE_STATUSES - ['running']).each do |build_status|
@@ -259,6 +265,15 @@ describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip')
end
+
+ context 'blocked user' do
+ let(:user) { create(:user, :blocked) }
+
+ it 'fails' do
+ expect(gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip'))
+ .to eq(Gitlab::Auth::Result.new(nil, nil, nil, nil))
+ end
+ end
end
context 'while using personal access tokens as passwords' do
@@ -307,9 +322,35 @@ describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
it 'fails if password is nil' do
expect_results_with_abilities(nil, nil, false)
end
+
+ context 'when user is blocked' do
+ let(:user) { create(:user, :blocked) }
+ let(:personal_access_token) { create(:personal_access_token, scopes: ['read_registry'], user: user) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ end
+
+ it 'fails if user is blocked' do
+ expect(gl_auth.find_for_git_client('', personal_access_token.token, project: nil, ip: 'ip'))
+ .to eq(Gitlab::Auth::Result.new(nil, nil, nil, nil))
+ end
+ end
end
context 'while using regular user and password' do
+ it 'fails for a blocked user' do
+ user = create(
+ :user,
+ :blocked,
+ username: 'normal_user',
+ password: 'my-secret'
+ )
+
+ expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip'))
+ .to eq(Gitlab::Auth::Result.new(nil, nil, nil, nil))
+ end
+
it 'goes through lfs authentication' do
user = create(
:user,
diff --git a/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb
index 5a930d44dcb..ebd7c7af265 100644
--- a/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb
+++ b/spec/lib/gitlab/gfm/uploads_rewriter_spec.rb
@@ -68,6 +68,16 @@ describe Gitlab::Gfm::UploadsRewriter do
expect(moved_text.scan(/\A\[.*?\]/).count).to eq(1)
end
+ context 'path traversal in file name' do
+ let(:text) do
+ "![a](/uploads/11111111111111111111111111111111/../../../../../../../../../../../../../../etc/passwd)"
+ end
+
+ it 'throw an error' do
+ expect { rewriter.rewrite(new_project) }.to raise_error(an_instance_of(StandardError).and having_attributes(message: "Invalid path"))
+ end
+ end
+
context "file are stored locally" do
include_examples "files are accessible"
end
diff --git a/spec/lib/gitlab/hotlinking_detector_spec.rb b/spec/lib/gitlab/hotlinking_detector_spec.rb
new file mode 100644
index 00000000000..536d744c197
--- /dev/null
+++ b/spec/lib/gitlab/hotlinking_detector_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Gitlab::HotlinkingDetector do
+ describe ".intercept_hotlinking?" do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.intercept_hotlinking?(request) }
+
+ let(:request) { double("request", headers: headers) }
+ let(:headers) { {} }
+
+ context "hotlinked as media" do
+ where(:return_value, :accept_header) do
+ # These are default formats in modern browsers, and IE
+ false | "*/*"
+ false | "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
+ false | "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
+ false | "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
+ false | "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
+ false | "image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/msword, */*"
+ false | "text/html, application/xhtml+xml, image/jxr, */*"
+ false | "text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1"
+
+ # These are image request formats
+ true | "image/webp,*/*"
+ true | "image/png,image/*;q=0.8,*/*;q=0.5"
+ true | "image/webp,image/apng,image/*,*/*;q=0.8"
+ true | "image/png,image/svg+xml,image/*;q=0.8, */*;q=0.5"
+
+ # Video request formats
+ true | "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5"
+
+ # Audio request formats
+ true | "audio/webm,audio/ogg,audio/wav,audio/*;q=0.9,application/ogg;q=0.7,video/*;q=0.6,*/*;q=0.5"
+
+ # CSS request formats
+ true | "text/css,*/*;q=0.1"
+ true | "text/css"
+ true | "text/css,*/*;q=0.1"
+ end
+
+ with_them do
+ let(:headers) do
+ { "Accept" => accept_header }
+ end
+
+ it { is_expected.to be(return_value) }
+ end
+ end
+
+ context "hotlinked as a script" do
+ where(:return_value, :fetch_mode) do
+ # Standard navigation fetch modes
+ false | "navigate"
+ false | "nested-navigate"
+ false | "same-origin"
+
+ # Fetch modes when linking as JS
+ true | "cors"
+ true | "no-cors"
+ true | "websocket"
+ end
+
+ with_them do
+ let(:headers) do
+ { "Sec-Fetch-Mode" => fetch_mode }
+ end
+
+ it { is_expected.to be(return_value) }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb
index 12857f97f7c..65e99c0c3b8 100644
--- a/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb
+++ b/spec/lib/gitlab/import_export/attribute_cleaner_spec.rb
@@ -32,6 +32,9 @@ describe Gitlab::ImportExport::AttributeCleaner do
'issue_ids' => [1, 2, 3],
'merge_request_ids' => [1, 2, 3],
'note_ids' => [1, 2, 3],
+ 'remote_attachment_url' => 'http://something.dodgy',
+ 'remote_attachment_request_header' => 'bad value',
+ 'remote_attachment_urls' => %w(http://something.dodgy http://something.okay),
'attributes' => {
'issue_ids' => [1, 2, 3],
'merge_request_ids' => [1, 2, 3],
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index c580b46cf8d..f1b5393a2d8 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -3,9 +3,7 @@
require 'spec_helper'
describe Gitlab::Regex do
- describe '.project_name_regex' do
- subject { described_class.project_name_regex }
-
+ shared_examples_for 'project/group name regex' do
it { is_expected.to match('gitlab-ce') }
it { is_expected.to match('GitLab CE') }
it { is_expected.to match('100 lines') }
@@ -15,6 +13,34 @@ describe Gitlab::Regex do
it { is_expected.not_to match('?gitlab') }
end
+ shared_examples_for 'project/group name error message' do
+ it { is_expected.to eq("can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'.") }
+ end
+
+ describe '.project_name_regex' do
+ subject { described_class.project_name_regex }
+
+ it_behaves_like 'project/group name regex'
+ end
+
+ describe '.group_name_regex' do
+ subject { described_class.group_name_regex }
+
+ it_behaves_like 'project/group name regex'
+ end
+
+ describe '.project_name_regex_message' do
+ subject { described_class.project_name_regex_message }
+
+ it_behaves_like 'project/group name error message'
+ end
+
+ describe '.group_name_regex_message' do
+ subject { described_class.group_name_regex_message }
+
+ it_behaves_like 'project/group name error message'
+ end
+
describe '.environment_name_regex' do
subject { described_class.environment_name_regex }
diff --git a/spec/lib/uploaded_file_spec.rb b/spec/lib/uploaded_file_spec.rb
index 2bbbd67b13c..25536c07dd9 100644
--- a/spec/lib/uploaded_file_spec.rb
+++ b/spec/lib/uploaded_file_spec.rb
@@ -59,6 +59,16 @@ describe UploadedFile do
expect(subject.sha256).to eq('sha256')
expect(subject.remote_id).to eq('remote_id')
end
+
+ it 'handles a blank path' do
+ params['file.path'] = ''
+
+ # Not a real file, so can't determine size itself
+ params['file.size'] = 1.byte
+
+ expect { described_class.from_params(params, :file, upload_path) }
+ .not_to raise_error
+ end
end
end