Merge branch 'ac/fix-path-traversal' into 'security-10-3'

[10.3] Fix path traversal in gitlab-ci.yml cache:key

See merge request gitlab/gitlabhq!2270

(cherry picked from commit c32d0c6807dfd41d7838a35742e6d0986871b389)

df29094a Fix path traversal in gitlab-ci.yml cache:key
This commit is contained in:
Robert Speicher 2018-01-03 18:00:36 +00:00 committed by Stan Hu
parent 1f96512ba1
commit 954a44574f
4 changed files with 83 additions and 2 deletions

View File

@ -0,0 +1,5 @@
---
title: Fix path traversal in gitlab-ci.yml cache:key
merge_request:
author:
type: security

View File

@ -258,7 +258,7 @@ The `cache:key` variable can use any of the [predefined variables](../variables/
The default key is **default** across the project, therefore everything is The default key is **default** across the project, therefore everything is
shared between each pipelines and jobs by default, starting from GitLab 9.0. shared between each pipelines and jobs by default, starting from GitLab 9.0.
>**Note:** The `cache:key` variable cannot contain the `/` character. >**Note:** The `cache:key` variable cannot contain the `/` character, or the equivalent URI encoded `%2F`; a value made only of dots (`.`, `%2E`) is also forbidden.
--- ---

View File

@ -64,10 +64,24 @@ module Gitlab
include LegacyValidationHelpers include LegacyValidationHelpers
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
unless validate_string(value) if validate_string(value)
validate_path(record, attribute, value)
else
record.errors.add(attribute, 'should be a string or symbol') record.errors.add(attribute, 'should be a string or symbol')
end end
end end
private
def validate_path(record, attribute, value)
path = CGI.unescape(value.to_s)
if path.include?('/')
record.errors.add(attribute, 'cannot contain the "/" character')
elsif path == '.' || path == '..'
record.errors.add(attribute, 'cannot be "." or ".."')
end
end
end end
class RegexpValidator < ActiveModel::EachValidator class RegexpValidator < ActiveModel::EachValidator

View File

@ -4,6 +4,26 @@ describe Gitlab::Ci::Config::Entry::Key do
let(:entry) { described_class.new(config) } let(:entry) { described_class.new(config) }
describe 'validations' do describe 'validations' do
shared_examples 'key with slash' do
it 'is invalid' do
expect(entry).not_to be_valid
end
it 'reports errors with config value' do
expect(entry.errors).to include 'key config cannot contain the "/" character'
end
end
shared_examples 'key with only dots' do
it 'is invalid' do
expect(entry).not_to be_valid
end
it 'reports errors with config value' do
expect(entry.errors).to include 'key config cannot be "." or ".."'
end
end
context 'when entry config value is correct' do context 'when entry config value is correct' do
let(:config) { 'test' } let(:config) { 'test' }
@ -30,6 +50,48 @@ describe Gitlab::Ci::Config::Entry::Key do
end end
end end
end end
context 'when entry value contains slash' do
let(:config) { 'key/with/some/slashes' }
it_behaves_like 'key with slash'
end
context 'when entry value contains URI encoded slash (%2F)' do
let(:config) { 'key%2Fwith%2Fsome%2Fslashes' }
it_behaves_like 'key with slash'
end
context 'when entry value is a dot' do
let(:config) { '.' }
it_behaves_like 'key with only dots'
end
context 'when entry value is two dots' do
let(:config) { '..' }
it_behaves_like 'key with only dots'
end
context 'when entry value is a URI encoded dot (%2E)' do
let(:config) { '%2e' }
it_behaves_like 'key with only dots'
end
context 'when entry value is two URI encoded dots (%2E)' do
let(:config) { '%2E%2e' }
it_behaves_like 'key with only dots'
end
context 'when entry value is one dot and one URI encoded dot' do
let(:config) { '.%2e' }
it_behaves_like 'key with only dots'
end
end end
describe '.default' do describe '.default' do