New upstream version 10.7.6+dfsg
This commit is contained in:
parent
2d79e65d03
commit
d3fc7f9250
39 changed files with 167 additions and 272 deletions
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -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
15
Gemfile
|
@ -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
|
||||
|
|
42
Gemfile.lock
42
Gemfile.lock
|
@ -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)
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
10.7.5
|
||||
10.7.6
|
||||
|
|
|
@ -5,6 +5,7 @@ class ApplicationController < ActionController::Base
|
|||
include Gitlab::GonHelper
|
||||
include GitlabRoutingHelper
|
||||
include PageLayoutHelper
|
||||
include SafeParamsHelper
|
||||
include SentryHelper
|
||||
include WorkhorseHelper
|
||||
include EnforcesTwoFactorAuthentication
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -189,6 +189,6 @@ class GroupsController < Groups::ApplicationController
|
|||
|
||||
params[:id] = group.to_param
|
||||
|
||||
url_for(params)
|
||||
url_for(safe_params)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
11
app/helpers/safe_params_helper.rb
Normal file
11
app/helpers/safe_params_helper.rb
Normal 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
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -92,7 +92,7 @@ module Banzai
|
|||
def text
|
||||
return '' unless node
|
||||
|
||||
@text ||= node.text
|
||||
@text ||= EscapeUtils.escape_html(node.text)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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="  javascript:alert(\'XSS\');">foo</a>',
|
||||
output: '<a href="">foo</a>'
|
||||
output: '<a href>foo</a>'
|
||||
},
|
||||
|
||||
'protocol whitespace' => {
|
||||
|
|
|
@ -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) { '<img src="x" onerror="alert(42)">' }
|
||||
let(:results) { result(header(1, content)) }
|
||||
|
||||
it 'outputs escaped content' do
|
||||
expect(doc.inner_html).to include(content)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue