summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessio Caiazza <acaiazza@gitlab.com>2018-06-25 18:19:29 +0200
committerAlessio Caiazza <acaiazza@gitlab.com>2018-06-25 18:19:29 +0200
commit6dd181da163a6479afa695b72f9c99a1e437a7a2 (patch)
tree3abfe48bf57d69fb5d3c6e54907f3a5353dc9346
parentda8b8fe33bb6fe6bd017ea4182d7fb4f5888914c (diff)
parent43e7e0806b0f5d24a9363d322995dffa01666cf1 (diff)
downloadgitlab-ce-6dd181da163a6479afa695b72f9c99a1e437a7a2.tar.gz
Merge remote-tracking branch 'dev/master'
-rw-r--r--CHANGELOG.md38
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock12
-rw-r--r--Gemfile.rails5.lock12
-rw-r--r--app/finders/user_recent_events_finder.rb2
-rw-r--r--app/helpers/projects_helper.rb3
-rw-r--r--app/views/projects/graphs/charts.html.haml2
-rw-r--r--changelogs/unreleased/security-2682-fix-xss-for-markdown-toc.yml5
-rw-r--r--changelogs/unreleased/security-fj-bumping-sanitize-gem.yml5
-rw-r--r--changelogs/unreleased/security-html_escape_branch_name.yml5
-rw-r--r--changelogs/unreleased/security-html_escape_usernames.yml5
-rw-r--r--changelogs/unreleased/security-rd-do-not-show-internal-info-in-public-feed.yml5
-rw-r--r--lib/banzai/filter/sanitization_filter.rb3
-rw-r--r--lib/banzai/filter/table_of_contents_filter.rb2
-rw-r--r--spec/features/projects/graph_spec.rb20
-rw-r--r--spec/finders/user_recent_events_finder_spec.rb45
-rw-r--r--spec/helpers/projects_helper_spec.rb9
-rw-r--r--spec/lib/banzai/filter/sanitization_filter_spec.rb12
-rw-r--r--spec/lib/banzai/filter/table_of_contents_filter_spec.rb9
19 files changed, 166 insertions, 30 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eabacbc2e1d..72725122b8f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,17 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 11.0.1 (2018-06-21)
+
+### Security (5 changes)
+
+- Fix XSS vulnerability for table of content generation.
+- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
+- HTML escape branch name in project graphs page.
+- HTML escape the name of the user in ProjectsHelper#link_to_member.
+- Don't show events from internal projects for anonymous users in public feed.
+
+
## 11.0.0 (2018-06-22)
### Security (3 changes)
@@ -242,6 +253,17 @@ entry.
- Workhorse to send raw diff and patch for commits.
+## 10.8.5 (2018-06-21)
+
+### Security (5 changes)
+
+- Fix XSS vulnerability for table of content generation.
+- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
+- HTML escape branch name in project graphs page.
+- HTML escape the name of the user in ProjectsHelper#link_to_member.
+- Don't show events from internal projects for anonymous users in public feed.
+
+
## 10.8.4 (2018-06-06)
- No changes.
@@ -460,6 +482,22 @@ entry.
- Gitaly handles repository forks by default.
+## 10.7.6 (2018-06-21)
+
+### Security (6 changes)
+
+- Fix XSS vulnerability for table of content generation.
+- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
+- HTML escape branch name in project graphs page.
+- HTML escape the name of the user in ProjectsHelper#link_to_member.
+- Don't show events from internal projects for anonymous users in public feed.
+- XSS fix to use safe_params instead of params in url_for helpers.
+
+### Other (1 change)
+
+- Replacing gollum libraries for gitlab custom libs. !18343
+
+
## 10.7.5 (2018-05-28)
### Security (3 changes)
diff --git a/Gemfile b/Gemfile
index 945b5486437..93c6115eeec 100644
--- a/Gemfile
+++ b/Gemfile
@@ -230,7 +230,7 @@ gem 'ruby-fogbugz', '~> 0.2.1'
gem 'kubeclient', '~> 3.1.0'
# Sanitize user input
-gem 'sanitize', '~> 2.0'
+gem 'sanitize', '~> 4.6.5'
gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input
diff --git a/Gemfile.lock b/Gemfile.lock
index fdc8f54e9c9..8281c1eff9a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -295,13 +295,13 @@ GEM
flowdock (~> 0.7)
gitlab-grit (>= 2.4.1)
multi_json
- gitlab-gollum-lib (4.2.7.4)
+ gitlab-gollum-lib (4.2.7.5)
gemojione (~> 3.2)
github-markup (~> 1.6)
gollum-grit_adapter (~> 1.0)
nokogiri (>= 1.6.1, < 2.0)
rouge (~> 3.1)
- sanitize (~> 2.1)
+ sanitize (~> 4.6.4)
stringex (~> 2.6)
gitlab-gollum-rugged_adapter (0.4.4.1)
mime-types (>= 1.15)
@@ -514,6 +514,8 @@ GEM
netrc (0.11.0)
nokogiri (1.8.2)
mini_portile2 (~> 2.3.0)
+ nokogumbo (1.5.0)
+ nokogiri
numerizer (0.1.1)
oauth (0.5.4)
oauth2 (1.4.0)
@@ -804,8 +806,10 @@ GEM
et-orbi (~> 1.0)
rugged (0.27.2)
safe_yaml (1.0.4)
- sanitize (2.1.0)
+ sanitize (4.6.5)
+ crass (~> 1.0.2)
nokogiri (>= 1.4.4)
+ nokogumbo (~> 1.4)
sass (3.5.5)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@@ -1151,7 +1155,7 @@ DEPENDENCIES
ruby_parser (~> 3.8)
rufus-scheduler (~> 3.4)
rugged (~> 0.27)
- sanitize (~> 2.0)
+ sanitize (~> 4.6.5)
sass-rails (~> 5.0.6)
scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7)
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock
index 679318b9be5..52388f17c7c 100644
--- a/Gemfile.rails5.lock
+++ b/Gemfile.rails5.lock
@@ -298,13 +298,13 @@ GEM
flowdock (~> 0.7)
gitlab-grit (>= 2.4.1)
multi_json
- gitlab-gollum-lib (4.2.7.4)
+ gitlab-gollum-lib (4.2.7.5)
gemojione (~> 3.2)
github-markup (~> 1.6)
gollum-grit_adapter (~> 1.0)
nokogiri (>= 1.6.1, < 2.0)
rouge (~> 3.1)
- sanitize (~> 2.1)
+ sanitize (~> 4.6.4)
stringex (~> 2.6)
gitlab-gollum-rugged_adapter (0.4.4.1)
mime-types (>= 1.15)
@@ -518,6 +518,8 @@ GEM
nio4r (2.3.1)
nokogiri (1.8.2)
mini_portile2 (~> 2.3.0)
+ nokogumbo (1.5.0)
+ nokogiri
numerizer (0.1.1)
oauth (0.5.4)
oauth2 (1.4.0)
@@ -813,8 +815,10 @@ GEM
et-orbi (~> 1.0)
rugged (0.27.1)
safe_yaml (1.0.4)
- sanitize (2.1.0)
+ sanitize (4.6.5)
+ crass (~> 1.0.2)
nokogiri (>= 1.4.4)
+ nokogumbo (~> 1.4)
sass (3.5.5)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@@ -1162,7 +1166,7 @@ DEPENDENCIES
ruby_parser (~> 3.8)
rufus-scheduler (~> 3.4)
rugged (~> 0.27)
- sanitize (~> 2.0)
+ sanitize (~> 4.6.5)
sass-rails (~> 5.0.6)
scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7)
diff --git a/app/finders/user_recent_events_finder.rb b/app/finders/user_recent_events_finder.rb
index 65d6e019746..74776b2ed1f 100644
--- a/app/finders/user_recent_events_finder.rb
+++ b/app/finders/user_recent_events_finder.rb
@@ -56,7 +56,7 @@ class UserRecentEventsFinder
visible = target_user
.project_interactions
- .where(visibility_level: [Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC])
+ .where(visibility_level: Gitlab::VisibilityLevel.levels_for_user(current_user))
.select(:id)
Gitlab::SQL::Union.new([authorized, visible]).to_sql
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index f479ed0f54c..c7a434ea092 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -40,7 +40,8 @@ module ProjectsHelper
name_tag_options[:class] << 'has-tooltip'
end
- content_tag(:span, sanitize(username), name_tag_options)
+ # NOTE: ActionView::Helpers::TagHelper#content_tag HTML escapes username
+ content_tag(:span, username, name_tag_options)
end
def link_to_member(project, author, opts = {}, &block)
diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml
index 983cb187c2f..3f1974d05f4 100644
--- a/app/views/projects/graphs/charts.html.haml
+++ b/app/views/projects/graphs/charts.html.haml
@@ -30,7 +30,7 @@
#{@commits_graph.start_date.strftime('%b %d')}
- end_time = capture do
#{@commits_graph.end_date.strftime('%b %d')}
- = (_("Commit statistics for %{ref} %{start_time} - %{end_time}") % { ref: "<strong>#{@ref}</strong>", start_time: start_time, end_time: end_time }).html_safe
+ = (_("Commit statistics for %{ref} %{start_time} - %{end_time}") % { ref: "<strong>#{h @ref}</strong>", start_time: start_time, end_time: end_time }).html_safe
.col-md-6
.tree-ref-container
diff --git a/changelogs/unreleased/security-2682-fix-xss-for-markdown-toc.yml b/changelogs/unreleased/security-2682-fix-xss-for-markdown-toc.yml
new file mode 100644
index 00000000000..f595678c3c2
--- /dev/null
+++ b/changelogs/unreleased/security-2682-fix-xss-for-markdown-toc.yml
@@ -0,0 +1,5 @@
+---
+title: Fix XSS vulnerability for table of content generation
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-fj-bumping-sanitize-gem.yml b/changelogs/unreleased/security-fj-bumping-sanitize-gem.yml
new file mode 100644
index 00000000000..bec1033425d
--- /dev/null
+++ b/changelogs/unreleased/security-fj-bumping-sanitize-gem.yml
@@ -0,0 +1,5 @@
+---
+title: Update sanitize gem to 4.6.5 to fix HTML injection vulnerability
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-html_escape_branch_name.yml b/changelogs/unreleased/security-html_escape_branch_name.yml
new file mode 100644
index 00000000000..02d1065348f
--- /dev/null
+++ b/changelogs/unreleased/security-html_escape_branch_name.yml
@@ -0,0 +1,5 @@
+---
+title: HTML escape branch name in project graphs page
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-html_escape_usernames.yml b/changelogs/unreleased/security-html_escape_usernames.yml
new file mode 100644
index 00000000000..7e69e4ae266
--- /dev/null
+++ b/changelogs/unreleased/security-html_escape_usernames.yml
@@ -0,0 +1,5 @@
+---
+title: HTML escape the name of the user in ProjectsHelper#link_to_member
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-rd-do-not-show-internal-info-in-public-feed.yml b/changelogs/unreleased/security-rd-do-not-show-internal-info-in-public-feed.yml
new file mode 100644
index 00000000000..ff78c162dff
--- /dev/null
+++ b/changelogs/unreleased/security-rd-do-not-show-internal-info-in-public-feed.yml
@@ -0,0 +1,5 @@
+---
+title: Don't show events from internal projects for anonymous users in public feed
+merge_request:
+author:
+type: security
diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb
index 6786b9d07b6..afc2ca4e362 100644
--- a/lib/banzai/filter/sanitization_filter.rb
+++ b/lib/banzai/filter/sanitization_filter.rb
@@ -25,10 +25,11 @@ module Banzai
# Only push these customizations once
return if customized?(whitelist[:transformers])
- # Allow table alignment; we whitelist specific style properties in a
+ # Allow table alignment; we whitelist specific text-align values in a
# transformer below
whitelist[:attributes]['th'] = %w(style)
whitelist[:attributes]['td'] = %w(style)
+ whitelist[:css] = { properties: ['text-align'] }
# Allow span elements
whitelist[:elements].push('span')
diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb
index 97244159985..b32660a8341 100644
--- a/lib/banzai/filter/table_of_contents_filter.rb
+++ b/lib/banzai/filter/table_of_contents_filter.rb
@@ -92,7 +92,7 @@ module Banzai
def text
return '' unless node
- @text ||= node.text
+ @text ||= EscapeUtils.escape_html(node.text)
end
private
diff --git a/spec/features/projects/graph_spec.rb b/spec/features/projects/graph_spec.rb
index 57172610aed..335174b7729 100644
--- a/spec/features/projects/graph_spec.rb
+++ b/spec/features/projects/graph_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
describe 'Project Graph', :js do
let(:user) { create :user }
let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let(:branch_name) { 'master' }
before do
project.add_master(user)
@@ -12,7 +13,7 @@ describe 'Project Graph', :js do
shared_examples 'page should have commits graphs' do
it 'renders commits' do
- expect(page).to have_content('Commit statistics for master')
+ expect(page).to have_content("Commit statistics for #{branch_name}")
expect(page).to have_content('Commits per day of month')
end
end
@@ -57,6 +58,23 @@ describe 'Project Graph', :js do
it_behaves_like 'page should have languages graphs'
end
+ context 'chart graph with HTML escaped branch name' do
+ let(:branch_name) { '<h1>evil</h1>' }
+
+ before do
+ project.repository.create_branch(branch_name, 'master')
+
+ visit charts_project_graph_path(project, branch_name)
+ end
+
+ it_behaves_like 'page should have commits graphs'
+
+ it 'HTML escapes branch name' do
+ expect(page.body).to include("Commit statistics for <strong>#{ERB::Util.html_escape(branch_name)}</strong>")
+ expect(page.body).not_to include(branch_name)
+ end
+ end
+
context 'when CI enabled' do
before do
project.enable_ci
diff --git a/spec/finders/user_recent_events_finder_spec.rb b/spec/finders/user_recent_events_finder_spec.rb
index 3ca0f7c3c89..da043f94021 100644
--- a/spec/finders/user_recent_events_finder_spec.rb
+++ b/spec/finders/user_recent_events_finder_spec.rb
@@ -1,31 +1,50 @@
require 'spec_helper'
describe UserRecentEventsFinder do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
- let(:project_owner) { project.creator }
- let!(:event) { create(:event, project: project, author: project_owner) }
+ let(:current_user) { create(:user) }
+ let(:project_owner) { create(:user) }
+ let(:private_project) { create(:project, :private, creator: project_owner) }
+ let(:internal_project) { create(:project, :internal, creator: project_owner) }
+ let(:public_project) { create(:project, :public, creator: project_owner) }
+ let!(:private_event) { create(:event, project: private_project, author: project_owner) }
+ let!(:internal_event) { create(:event, project: internal_project, author: project_owner) }
+ let!(:public_event) { create(:event, project: public_project, author: project_owner) }
- subject(:finder) { described_class.new(user, project_owner) }
+ subject(:finder) { described_class.new(current_user, project_owner) }
describe '#execute' do
- it 'does not include the event when a user does not have access to the project' do
- expect(finder.execute).to be_empty
+ context 'current user does not have access to projects' do
+ it 'returns public and internal events' do
+ records = finder.execute
+
+ expect(records).to include(public_event, internal_event)
+ expect(records).not_to include(private_event)
+ end
end
- context 'when the user has access to a project' do
+ context 'when current user has access to the projects' do
before do
- project.add_developer(user)
+ private_project.add_developer(current_user)
+ internal_project.add_developer(current_user)
+ public_project.add_developer(current_user)
end
- it 'includes the event' do
- expect(finder.execute).to include(event)
+ it 'returns all the events' do
+ expect(finder.execute).to include(private_event, internal_event, public_event)
end
- it 'does not include the event if the user cannot read cross project' do
- expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
+ it 'does not include the events if the user cannot read cross project' do
+ expect(Ability).to receive(:allowed?).with(current_user, :read_cross_project) { false }
expect(finder.execute).to be_empty
end
end
+
+ context 'when current user is anonymous' do
+ let(:current_user) { nil }
+
+ it 'returns public events only' do
+ expect(finder.execute).to eq([public_event])
+ end
+ end
end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 5cf9e9e8f12..80147b13739 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -248,7 +248,7 @@ describe ProjectsHelper do
describe '#link_to_member' do
let(:group) { build_stubbed(:group) }
let(:project) { build_stubbed(:project, group: group) }
- let(:user) { build_stubbed(:user) }
+ let(:user) { build_stubbed(:user, name: '<h1>Administrator</h1>') }
describe 'using the default options' do
it 'returns an HTML link to the user' do
@@ -256,6 +256,13 @@ describe ProjectsHelper do
expect(link).to match(%r{/#{user.username}})
end
+
+ it 'HTML escapes the name of the user' do
+ link = helper.link_to_member(project, user)
+
+ expect(link).to include(ERB::Util.html_escape(user.name))
+ expect(link).not_to include(user.name)
+ end
end
end
diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb
index 17a620ef603..d930c608b18 100644
--- a/spec/lib/banzai/filter/sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb
@@ -93,6 +93,16 @@ describe Banzai::Filter::SanitizationFilter do
expect(doc.at_css('td')['style']).to eq 'text-align: center'
end
+ it 'disallows `text-align` property in `style` attribute on other elements' do
+ html = <<~HTML
+ <div style="text-align: center">Text</div>
+ HTML
+
+ doc = filter(html)
+
+ expect(doc.at_css('div')['style']).to be_nil
+ end
+
it 'allows `span` elements' do
exp = act = %q{<span>Hello</span>}
expect(filter(act).to_html).to eq exp
@@ -224,7 +234,7 @@ describe Banzai::Filter::SanitizationFilter do
'protocol-based JS injection: spaces and entities' => {
input: '<a href=" &#14; javascript:alert(\'XSS\');">foo</a>',
- output: '<a href="">foo</a>'
+ output: '<a href>foo</a>'
},
'protocol whitespace' => {
diff --git a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
index 0cfef4ff5bf..7213cd58ea7 100644
--- a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
+++ b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
@@ -139,5 +139,14 @@ describe Banzai::Filter::TableOfContentsFilter do
expect(items[5].ancestors).to include(items[4])
end
end
+
+ context 'header text contains escaped content' do
+ let(:content) { '&lt;img src="x" onerror="alert(42)"&gt;' }
+ let(:results) { result(header(1, content)) }
+
+ it 'outputs escaped content' do
+ expect(doc.inner_html).to include(content)
+ end
+ end
end
end