Commit 976a25c8 authored by Aishwarya Subramanian's avatar Aishwarya Subramanian

Prevent malicious entry for group name

Prevent malicious script being saved as a group name
Fixed failing spec
Addressed review comments
parent 2f524f96
......@@ -70,6 +70,9 @@ class Group < Namespace
validates :variables, variable_duplicates: true
validates :two_factor_grace_period, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :name,
format: { with: Gitlab::Regex.group_name_regex,
message: Gitlab::Regex.group_name_regex_message }
add_authentication_token_field :runners_token, encrypted: -> { Feature.enabled?(:groups_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
......
---
title: Prevent malicious entry for group name
merge_request:
author:
type: security
......@@ -187,7 +187,7 @@ describe SubscriptionsController do
group.save
subject
expect(response.body).to eq({ name: ["can't be blank"] }.to_json)
expect(response.body).to include({ name: ["can't be blank", Gitlab::Regex.group_name_regex_message] }.to_json)
end
end
......
......@@ -16,6 +16,14 @@ module Gitlab
"It must start with letter, digit, emoji or '_'."
end
def group_name_regex
project_name_regex
end
def group_name_regex_message
project_name_regex_message
end
##
# Docker Distribution Registry repository / tag name rules
#
......
......@@ -258,6 +258,18 @@ describe GroupsController do
end
end
end
context "malicious group name" do
subject { post :create, params: { group: { name: "<script>alert('Mayday!');</script>", path: "invalid_group_url" } } }
before do
sign_in(user)
end
it { expect { subject }.not_to change { Group.count } }
it { expect(subject).to render_template(:new) }
end
end
describe 'GET #index' do
......@@ -836,6 +848,16 @@ describe GroupsController do
put :update, params: { id: group.to_param, group: { name: 'world' } }
end.to change { group.reload.name }
end
context "malicious group name" do
subject { put :update, params: { id: group.to_param, group: { name: "<script>alert('Attack!');</script>" } } }
it { is_expected.to render_template(:edit) }
it 'does not update name' do
expect { subject }.not_to change { group.reload.name }
end
end
end
describe 'DELETE #destroy' do
......
......@@ -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)
......
......@@ -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 }
......
......@@ -48,6 +48,9 @@ describe Group do
describe 'validations' do
it { is_expected.to validate_presence_of :name }
it { is_expected.to allow_value('group test_4').for(:name) }
it { is_expected.not_to allow_value('test/../foo').for(:name) }
it { is_expected.not_to allow_value('<script>alert("Attack!")</script>').for(:name) }
it { is_expected.to validate_presence_of :path }
it { is_expected.not_to validate_presence_of :owner }
it { is_expected.to validate_presence_of :two_factor_grace_period }
......
......@@ -620,6 +620,20 @@ describe API::Groups do
expect(json_response['default_branch_protection']).to eq(::Gitlab::Access::MAINTAINER_PROJECT_ACCESS)
end
context 'malicious group name' do
subject { put api("/groups/#{group1.id}", user1), params: { name: "<SCRIPT>alert('DOUBLE-ATTACK!')</SCRIPT>" } }
it 'returns bad request' do
subject
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'does not update group name' do
expect { subject }.not_to change { group1.reload.name }
end
end
it 'returns 404 for a non existing group' do
put api('/groups/1328', user1), params: { name: new_group_name }
......@@ -1061,6 +1075,20 @@ describe API::Groups do
expect(json_response["parent_id"]).to eq(parent.id)
end
context 'malicious group name' do
subject { post api("/groups", user3), params: group_params }
let(:group_params) { attributes_for_group_api name: "<SCRIPT>alert('ATTACKED!')</SCRIPT>", path: "unique-url" }
it 'returns bad request' do
subject
expect(response).to have_gitlab_http_status(:bad_request)
end
it { expect { subject }.not_to change { Group.count } }
end
it "does not create group, duplicate" do
post api("/groups", user3), params: { name: 'Duplicate Test', path: group2.path }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment