New upstream version 10.7.6+dfsg

This commit is contained in:
Pirate Praveen 2018-06-27 16:04:02 +05:30
parent 2d79e65d03
commit d3fc7f9250
39 changed files with 167 additions and 272 deletions

View file

@ -2,6 +2,22 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 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)

15
Gemfile
View file

@ -81,16 +81,9 @@ gem 'net-ldap'
# Git Wiki
# Required manually in config/initializers/gollum.rb to control load order
# Before updating this gem, check if
# https://github.com/gollum/gollum-lib/pull/292 has been merged.
# If it has, then remove the monkey patch for update_page, rename_page and raw_data_in_committer
# in config/initializers/gollum.rb
gem 'gollum-lib', '~> 4.2', require: false
gem 'gitlab-gollum-lib', '~> 4.2'
# Before updating this gem, check if
# https://github.com/gollum/rugged_adapter/pull/28 has been merged.
# If it has, then remove the monkey patch for tree_entry in config/initializers/gollum.rb
gem 'gollum-rugged_adapter', '~> 0.4.4', require: false
gem 'gitlab-gollum-rugged_adapter', '~> 0.4.4', require: false
# Language detection
gem 'github-linguist', '~> 5.3.3', require: 'linguist'
@ -146,7 +139,7 @@ gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.6'
gem 'asciidoctor-plantuml', '0.0.8'
gem 'rouge', '~> 2.0'
gem 'rouge', '~> 3.1'
gem 'truncato', '~> 0.7.9'
gem 'bootstrap_form', '~> 2.7.0'
gem 'nokogiri', '~> 1.8.2'
@ -226,7 +219,7 @@ gem 'kubeclient', '~> 3.0'
gem 'd3_rails', '~> 3.5.0'
# Sanitize user input
gem 'sanitize', '~> 2.0'
gem 'sanitize', '~> 4.6.5'
gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input

View file

@ -298,11 +298,22 @@ GEM
escape_utils (~> 1.1.0)
mime-types (>= 1.19)
rugged (>= 0.25.1)
github-markup (1.6.1)
github-markup (1.7.0)
gitlab-flowdock-git-hook (1.0.1)
flowdock (~> 0.7)
gitlab-grit (>= 2.4.1)
multi_json
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 (~> 4.6.4)
stringex (~> 2.6)
gitlab-gollum-rugged_adapter (0.4.4)
mime-types (>= 1.15)
rugged (~> 0.25)
gitlab-grit (2.8.2)
charlock_holmes (~> 0.6)
diff-lcs (~> 1.1)
@ -322,17 +333,6 @@ GEM
activesupport (>= 4.2.0)
gollum-grit_adapter (1.0.1)
gitlab-grit (~> 2.7, >= 2.7.1)
gollum-lib (4.2.7)
gemojione (~> 3.2)
github-markup (~> 1.6)
gollum-grit_adapter (~> 1.0)
nokogiri (>= 1.6.1, < 2.0)
rouge (~> 2.1)
sanitize (~> 2.1)
stringex (~> 2.6)
gollum-rugged_adapter (0.4.4)
mime-types (>= 1.15)
rugged (~> 0.25)
gon (6.1.0)
actionpack (>= 3.0)
json
@ -517,6 +517,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)
@ -744,7 +746,7 @@ GEM
retriable (3.1.1)
rinku (2.0.0)
rotp (2.1.2)
rouge (2.2.1)
rouge (3.1.1)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
@ -812,8 +814,10 @@ GEM
et-orbi (~> 1.0)
rugged (0.27.0)
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)
@ -904,7 +908,7 @@ GEM
state_machines-activerecord (0.5.1)
activerecord (>= 4.1, < 6.0)
state_machines-activemodel (>= 0.5.0)
stringex (2.7.1)
stringex (2.8.4)
sys-filesystem (1.1.6)
ffi
sysexits (1.2.0)
@ -1061,11 +1065,11 @@ DEPENDENCIES
gitaly-proto (~> 0.96.0)
github-linguist (~> 5.3.3)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2)
gitlab-gollum-rugged_adapter (~> 0.4.4)
gitlab-markup (~> 1.6.2)
gitlab-styles (~> 2.3)
gitlab_omniauth-ldap (~> 2.0.4)
gollum-lib (~> 4.2)
gollum-rugged_adapter (~> 0.4.4)
gon (~> 6.1.0)
google-api-client (~> 0.19.8)
google-protobuf (= 3.5.1)
@ -1156,7 +1160,7 @@ DEPENDENCIES
redis-rails (~> 5.0.2)
request_store (~> 1.3)
responders (~> 2.0)
rouge (~> 2.0)
rouge (~> 3.1)
rqrcode-rails3 (~> 0.1.7)
rspec-parameterized
rspec-rails (~> 3.6.0)
@ -1170,7 +1174,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)

View file

@ -1 +1 @@
10.7.5
10.7.6

View file

@ -5,6 +5,7 @@ class ApplicationController < ActionController::Base
include Gitlab::GonHelper
include GitlabRoutingHelper
include PageLayoutHelper
include SafeParamsHelper
include SentryHelper
include WorkhorseHelper
include EnforcesTwoFactorAuthentication

View file

@ -57,7 +57,7 @@ module IssuableCollections
out_of_range = @issuables.current_page > total_pages # rubocop:disable Gitlab/ModuleWithInstanceVariables
if out_of_range
redirect_to(url_for(params.merge(page: total_pages, only_path: true)))
redirect_to(url_for(safe_params.merge(page: total_pages, only_path: true)))
end
out_of_range

View file

@ -86,7 +86,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
out_of_range = todos.current_page > total_pages
if out_of_range
redirect_to url_for(params.merge(page: total_pages, only_path: true))
redirect_to url_for(safe_params.merge(page: total_pages, only_path: true))
end
out_of_range

View file

@ -33,6 +33,6 @@ class Groups::ApplicationController < ApplicationController
def build_canonical_path(group)
params[:group_id] = group.to_param
url_for(params)
url_for(safe_params)
end
end

View file

@ -189,6 +189,6 @@ class GroupsController < Groups::ApplicationController
params[:id] = group.to_param
url_for(params)
url_for(safe_params)
end
end

View file

@ -25,7 +25,7 @@ class Projects::ApplicationController < ApplicationController
params[:namespace_id] = project.namespace.to_param
params[:project_id] = project.to_param
url_for(params)
url_for(safe_params)
end
def repository

View file

@ -404,7 +404,7 @@ class ProjectsController < Projects::ApplicationController
params[:namespace_id] = project.namespace.to_param
params[:id] = project.to_param
url_for(params)
url_for(safe_params)
end
def project_export_enabled

View file

@ -146,6 +146,6 @@ class UsersController < ApplicationController
end
def build_canonical_path(user)
url_for(params.merge(username: user.to_param))
url_for(safe_params.merge(username: user.to_param))
end
end

View file

@ -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

View file

@ -259,7 +259,7 @@ module BlobHelper
options = []
if error == :collapsed
options << link_to('load it anyway', url_for(params.merge(viewer: viewer.type, expanded: true, format: nil)))
options << link_to('load it anyway', url_for(safe_params.merge(viewer: viewer.type, expanded: true, format: nil)))
end
# If the error is `:server_side_but_stored_externally`, the simple viewer will show the same error,

View file

@ -180,7 +180,7 @@ module DiffHelper
private
def diff_btn(title, name, selected)
params_copy = params.dup
params_copy = safe_params.dup
params_copy[:view] = name
# Always use HTML to handle case where JSON diff rendered this button

View file

@ -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)

View file

@ -0,0 +1,11 @@
module SafeParamsHelper
# Rails 5.0 requires to permit parameters if used in url helpers.
# Use this helper when generating links with `params.merge(...)`
def safe_params
if params.respond_to?(:permit!)
params.except(:host, :port, :protocol).permit!
else
params
end
end
end

View file

@ -1,5 +1,5 @@
xml.title "#{current_user.name} issues"
xml.link href: url_for(params), rel: "self", type: "application/atom+xml"
xml.link href: url_for(safe_params), rel: "self", type: "application/atom+xml"
xml.link href: issues_dashboard_url, rel: "alternate", type: "text/html"
xml.id issues_dashboard_url
xml.updated @issues.first.updated_at.xmlschema if @issues.reorder(nil).any?

View file

@ -2,12 +2,12 @@
- page_title _("Issues")
- @breadcrumb_link = issues_dashboard_path(assignee_id: current_user.id)
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{current_user.name} issues")
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{current_user.name} issues")
.top-area
= render 'shared/issuable/nav', type: :issues, display_count: !@no_filters_set
.nav-controls
= link_to params.merge(rss_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: 'Subscribe' do
= link_to safe_params.merge(rss_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: 'Subscribe' do
= icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues

View file

@ -1,5 +1,5 @@
xml.title "#{@group.name} issues"
xml.link href: url_for(params), rel: "self", type: "application/atom+xml"
xml.link href: url_for(safe_params), rel: "self", type: "application/atom+xml"
xml.link href: issues_group_url, rel: "alternate", type: "text/html"
xml.id issues_group_url
xml.updated @issues.first.updated_at.xmlschema if @issues.reorder(nil).any?

View file

@ -1,6 +1,6 @@
- page_title "Issues"
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@group.name} issues")
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@group.name} issues")
- if group_issues_count(state: 'all').zero?
= render 'shared/empty_states/issues', project_select_button: true

View file

@ -3,7 +3,7 @@
#js-peek{ data: { env: Peek.env,
request_id: Peek.request_id,
peek_url: peek_routes.results_url,
profile_url: url_for(params.merge(lineprofiler: 'true')) },
profile_url: url_for(safe_params.merge(lineprofiler: 'true')) },
class: Peek.env }
#peek-view-performance-bar.hidden

View file

@ -3,7 +3,7 @@
- rich_type = viewer.type == :rich ? viewer.partial_name : nil
- load_async = local_assigns.fetch(:load_async, viewer.load_async? && render_error.nil?)
- viewer_url = local_assigns.fetch(:viewer_url) { url_for(params.merge(viewer: viewer.type, format: :json)) } if load_async
- viewer_url = local_assigns.fetch(:viewer_url) { url_for(safe_params.merge(viewer: viewer.type, format: :json)) } if load_async
.blob-viewer{ data: { type: viewer.type, rich_type: rich_type, url: viewer_url }, class: ('hidden' if hidden) }
- if render_error
= render 'projects/blob/render_error', viewer: viewer

View file

@ -1,5 +1,5 @@
- diff_file = viewer.diff_file
- url = url_for(params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path, file_identifier: diff_file.file_identifier))
- url = url_for(safe_params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path, file_identifier: diff_file.file_identifier))
.nothing-here-block.diff-collapsed{ data: { diff_for_path: url } }
This diff is collapsed.
%a.click-to-expand Click to expand it.

View file

@ -8,7 +8,7 @@
.files-changed-inner
.inline-parallel-buttons.hidden-xs.hidden-sm
- if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? }
= link_to 'Expand all', url_for(params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
= link_to 'Expand all', url_for(safe_params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
- if show_whitespace_toggle
- if current_controller?(:commit)
= commit_diff_whitespace_link(diffs.project, @commit, class: 'hidden-xs')

View file

@ -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

View file

@ -1,4 +1,4 @@
= link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10 has-tooltip', title: 'Subscribe' do
= link_to safe_params.merge(rss_url_options), class: 'btn btn-default append-right-10 has-tooltip', title: 'Subscribe' do
= icon('rss')
- if @can_bulk_update
= button_tag "Edit issues", class: "btn btn-default append-right-10 js-bulk-update-toggle"

View file

@ -1,5 +1,5 @@
xml.title "#{@project.name} issues"
xml.link href: url_for(params), rel: "self", type: "application/atom+xml"
xml.link href: url_for(safe_params), rel: "self", type: "application/atom+xml"
xml.link href: project_issues_url(@project), rel: "alternate", type: "text/html"
xml.id project_issues_url(@project)
xml.updated @issues.first.updated_at.xmlschema if @issues.reorder(nil).any?

View file

@ -5,7 +5,7 @@
- new_issue_email = @project.new_issuable_address(current_user, 'issue')
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@project.name} issues")
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@project.name} issues")
- if project_issues(@project).exists?
%div{ class: (container_class) }

View file

@ -26,16 +26,16 @@
- else
%ul.merge-request-tabs.nav-links.no-top.no-bottom
%li.commits-tab.active
= link_to url_for(params), data: {target: 'div#commits', action: 'new', toggle: 'tab'} do
= link_to url_for(safe_params), data: {target: 'div#commits', action: 'new', toggle: 'tab'} do
Commits
%span.badge= @commits.size
- if @pipelines.any?
%li.builds-tab
= link_to url_for(params.merge(action: 'pipelines')), data: {target: 'div#pipelines', action: 'pipelines', toggle: 'tab'} do
= link_to url_for(safe_params.merge(action: 'pipelines')), data: {target: 'div#pipelines', action: 'pipelines', toggle: 'tab'} do
Pipelines
%span.badge= @pipelines.size
%li.diffs-tab
= link_to url_for(params.merge(action: 'diffs')), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
= link_to url_for(safe_params.merge(action: 'diffs')), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
Changes
%span.badge= @merge_request.diff_size
@ -46,7 +46,7 @@
-# This tab is always loaded via AJAX
- if @pipelines.any?
#pipelines.pipelines.tab-pane
= render 'projects/merge_requests/pipelines', endpoint: url_for(params.merge(action: 'pipelines', format: :json)), disable_initialization: true
= render 'projects/merge_requests/pipelines', endpoint: url_for(safe_params.merge(action: 'pipelines', format: :json)), disable_initialization: true
.mr-loading-status
= spinner

View file

@ -7,139 +7,6 @@ module Gollum
end
require "gollum-lib"
module Gollum
class Committer
# Patch for UTF-8 path
def method_missing(name, *args)
index.send(name, *args)
end
end
class Wiki
def pages(treeish = nil, limit: nil)
tree_list((treeish || @ref), limit: limit)
end
def tree_list(ref, limit: nil)
if (sha = @access.ref_to_sha(ref))
commit = @access.commit(sha)
tree_map_for(sha).inject([]) do |list, entry|
next list unless @page_class.valid_page_name?(entry.name)
list << entry.page(self, commit)
break list if limit && list.size >= limit
list
end
else
[]
end
end
# Remove if https://github.com/gollum/gollum-lib/pull/292 has been merged
def update_page(page, name, format, data, commit = {})
name = name ? ::File.basename(name) : page.name
format ||= page.format
dir = ::File.dirname(page.path)
dir = '' if dir == '.'
filename = (rename = page.name != name) ? Gollum::Page.cname(name) : page.filename_stripped
multi_commit = !!commit[:committer]
committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
if !rename && page.format == format
committer.add(page.path, normalize(data))
else
committer.delete(page.path)
committer.add_to_index(dir, filename, format, data)
end
committer.after_commit do |index, _sha|
@access.refresh
index.update_working_dir(dir, page.filename_stripped, page.format)
index.update_working_dir(dir, filename, format)
end
multi_commit ? committer : committer.commit
end
# Remove if https://github.com/gollum/gollum-lib/pull/292 has been merged
def rename_page(page, rename, commit = {})
return false if page.nil?
return false if rename.nil? || rename.empty?
(target_dir, target_name) = ::File.split(rename)
(source_dir, source_name) = ::File.split(page.path)
source_name = page.filename_stripped
# File.split gives us relative paths with ".", commiter.add_to_index doesn't like that.
target_dir = '' if target_dir == '.'
source_dir = '' if source_dir == '.'
target_dir = target_dir.gsub(/^\//, '') # rubocop:disable Style/RegexpLiteral
# if the rename is a NOOP, abort
if source_dir == target_dir && source_name == target_name
return false
end
multi_commit = !!commit[:committer]
committer = multi_commit ? commit[:committer] : Committer.new(self, commit)
# This piece only works for multi_commit
# If we are in a commit batch and one of the previous operations
# has updated the page, any information we ask to the page can be outdated.
# Therefore, we should ask first to the current committer tree to see if
# there is any updated change.
raw_data = raw_data_in_committer(committer, source_dir, page.filename) ||
raw_data_in_committer(committer, source_dir, "#{target_name}.#{Page.format_to_ext(page.format)}") ||
page.raw_data
committer.delete(page.path)
committer.add_to_index(target_dir, target_name, page.format, raw_data)
committer.after_commit do |index, _sha|
@access.refresh
index.update_working_dir(source_dir, source_name, page.format)
index.update_working_dir(target_dir, target_name, page.format)
end
multi_commit ? committer : committer.commit
end
# Remove if https://github.com/gollum/gollum-lib/pull/292 has been merged
def raw_data_in_committer(committer, dir, filename)
data = nil
[*dir.split(::File::SEPARATOR), filename].each do |key|
data = data ? data[key] : committer.tree[key]
break unless data
end
data
end
end
module Git
class Git
def tree_entry(commit, path)
pathname = Pathname.new(path)
tmp_entry = nil
pathname.each_filename do |dir|
tmp_entry = if tmp_entry.nil?
commit.tree[dir]
else
@repo.lookup(tmp_entry[:oid])[dir]
end
return nil unless tmp_entry
end
tmp_entry
end
end
end
end
Rails.application.configure do
config.after_initialize do
Gollum::Page.per_page = Kaminari.config.default_per_page

View file

@ -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')

View file

@ -92,7 +92,7 @@ module Banzai
def text
return '' unless node
@text ||= node.text
@text ||= EscapeUtils.escape_html(node.text)
end
private

View file

@ -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

View file

@ -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

View file

@ -244,7 +244,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
@ -252,6 +252,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

View file

@ -1,62 +0,0 @@
require 'spec_helper'
describe 'gollum' do
let(:project) { create(:project) }
let(:user) { project.owner }
let(:wiki) { ProjectWiki.new(project, user) }
let(:gollum_wiki) { Gollum::Wiki.new(wiki.repository.path) }
before do
create_page(page_name, 'content1')
end
after do
destroy_page(page_name)
end
context 'with simple paths' do
let(:page_name) { 'page1' }
it 'returns the entry hash if it matches the file name' do
expect(tree_entry(page_name)).not_to be_nil
end
it 'returns nil if the path does not fit completely' do
expect(tree_entry("foo/#{page_name}")).to be_nil
end
end
context 'with complex paths' do
let(:page_name) { '/foo/bar/page2' }
it 'returns the entry hash if it matches the file name' do
expect(tree_entry(page_name)).not_to be_nil
end
it 'returns nil if the path does not fit completely' do
expect(tree_entry("foo1/bar/page2")).to be_nil
expect(tree_entry("foo/bar1/page2")).to be_nil
end
end
def tree_entry(name)
gollum_wiki.repo.git.tree_entry(wiki_commits[0].commit, name + '.md')
end
def wiki_commits
gollum_wiki.repo.commits
end
def commit_details
Gitlab::Git::Wiki::CommitDetails.new(user.name, user.email, "test commit")
end
def create_page(name, content)
wiki.wiki.write_page(name, :markdown, content, commit_details)
end
def destroy_page(name)
page = wiki.find_page(name).page
wiki.delete_page(page, "test commit")
end
end

View file

@ -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' => {

View file

@ -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