diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-29 22:17:00 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-29 22:17:00 +0300 |
commit | 5b4f92ef7a4e402bb59834dfea7aa1b043b78017 (patch) | |
tree | 75e0391aa4acae72a43d64bd3049e0248f8628c4 /app | |
parent | d739e5f0720c5b614fcefd4df7939ec1fc4da758 (diff) |
Add latest changes from gitlab-org/security/gitlab@12-10-stable-ee
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/error_tracking/components/stacktrace_entry.vue | 57 | ||||
-rw-r--r-- | app/controllers/groups/application_controller.rb | 12 | ||||
-rw-r--r-- | app/controllers/groups/deploy_tokens_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/groups/settings/repository_controller.rb | 2 | ||||
-rw-r--r-- | app/models/group.rb | 7 | ||||
-rw-r--r-- | app/policies/group_policy.rb | 4 | ||||
-rw-r--r-- | app/validators/html_safety_validator.rb | 36 | ||||
-rw-r--r-- | app/views/import/bitbucket_server/status.html.haml | 4 | ||||
-rw-r--r-- | app/views/shared/notes/_note.html.haml | 2 |
9 files changed, 83 insertions, 43 deletions
diff --git a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue index 8db0b1c5da0..d806c6934a3 100644 --- a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue +++ b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue @@ -1,7 +1,5 @@ <script> -import { escape as esc } from 'lodash'; -import { GlTooltip } from '@gitlab/ui'; -import { __, sprintf } from '~/locale'; +import { GlTooltip, GlSprintf } from '@gitlab/ui'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import FileIcon from '~/vue_shared/components/file_icon.vue'; import Icon from '~/vue_shared/components/icon.vue'; @@ -11,6 +9,7 @@ export default { ClipboardButton, FileIcon, Icon, + GlSprintf, }, directives: { GlTooltip, @@ -57,36 +56,6 @@ export default { collapseIcon() { return this.isExpanded ? 'chevron-down' : 'chevron-right'; }, - errorFnText() { - return this.errorFn - ? sprintf( - __(`%{spanStart}in%{spanEnd} %{errorFn}`), - { - errorFn: `<strong>${esc(this.errorFn)}</strong>`, - spanStart: `<span class="text-tertiary">`, - spanEnd: `</span>`, - }, - false, - ) - : ''; - }, - errorPositionText() { - return this.errorLine - ? sprintf( - __(`%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}`), - { - errorLine: `<strong>${this.errorLine}</strong>`, - errorColumn: this.errorColumn ? `:<strong>${this.errorColumn}</strong>` : ``, - spanStart: `<span class="text-tertiary">`, - spanEnd: `</span>`, - }, - false, - ) - : ''; - }, - errorInfo() { - return `${this.errorFnText} ${this.errorPositionText}`; - }, }, methods: { isHighlighted(lineNum) { @@ -132,7 +101,27 @@ export default { :text="filePath" css-class="btn-default btn-transparent btn-clipboard position-static" /> - <span v-html="errorInfo"></span> + + <gl-sprintf v-if="errorFn" :message="__('%{spanStart}in%{spanEnd} %{errorFn}')"> + <template #span="{content}"> + <span class="gl-text-gray-400">{{ content }} </span> + </template> + <template #errorFn> + <strong>{{ errorFn }} </strong> + </template> + </gl-sprintf> + + <gl-sprintf :message="__('%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}')"> + <template #span="{content}"> + <span class="gl-text-gray-400">{{ content }} </span> + </template> + <template #errorLine> + <strong>{{ errorLine }}</strong> + </template> + <template #errorColumn> + <strong v-if="errorColumn">:{{ errorColumn }}</strong> + </template> + </gl-sprintf> </div> </div> diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 0760bdf1e01..84c8d7ada43 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -34,6 +34,18 @@ class Groups::ApplicationController < ApplicationController end end + def authorize_create_deploy_token! + unless can?(current_user, :create_deploy_token, group) + return render_404 + end + end + + def authorize_destroy_deploy_token! + unless can?(current_user, :destroy_deploy_token, group) + return render_404 + end + end + def authorize_admin_group_member! unless can?(current_user, :admin_group_member, group) return render_403 diff --git a/app/controllers/groups/deploy_tokens_controller.rb b/app/controllers/groups/deploy_tokens_controller.rb index 6bb075fd115..de951f2cb9f 100644 --- a/app/controllers/groups/deploy_tokens_controller.rb +++ b/app/controllers/groups/deploy_tokens_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Groups::DeployTokensController < Groups::ApplicationController - before_action :authorize_admin_group! + before_action :authorize_destroy_deploy_token! def revoke @token = @group.deploy_tokens.find(params[:id]) diff --git a/app/controllers/groups/settings/repository_controller.rb b/app/controllers/groups/settings/repository_controller.rb index 6e8c5628d24..dc825076c39 100644 --- a/app/controllers/groups/settings/repository_controller.rb +++ b/app/controllers/groups/settings/repository_controller.rb @@ -4,7 +4,7 @@ module Groups module Settings class RepositoryController < Groups::ApplicationController skip_cross_project_access_check :show - before_action :authorize_admin_group! + before_action :authorize_create_deploy_token! before_action :define_deploy_token_variables before_action do push_frontend_feature_flag(:ajax_new_deploy_token, @group) diff --git a/app/models/group.rb b/app/models/group.rb index 55a2c4ba9a9..704049698cc 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -70,9 +70,12 @@ 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 }, if: :name_changed? + html_safety: true, + format: { with: Gitlab::Regex.group_name_regex, + message: Gitlab::Regex.group_name_regex_message }, + if: :name_changed? add_authentication_token_field :runners_token, encrypted: -> { Feature.enabled?(:groups_tokens_optional_encryption, default_enabled: true) ? :optional : :required } diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index 728c4b76498..8949cb33c6e 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -109,9 +109,7 @@ class GroupPolicy < BasePolicy enable :create_cluster enable :update_cluster enable :admin_cluster - enable :destroy_deploy_token enable :read_deploy_token - enable :create_deploy_token enable :admin_wiki end @@ -123,6 +121,8 @@ class GroupPolicy < BasePolicy enable :set_note_created_at enable :set_emails_disabled + enable :create_deploy_token + enable :destroy_deploy_token end rule { can?(:read_nested_project_resources) }.policy do diff --git a/app/validators/html_safety_validator.rb b/app/validators/html_safety_validator.rb new file mode 100644 index 00000000000..29e7d445697 --- /dev/null +++ b/app/validators/html_safety_validator.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +# HtmlSafetyValidator +# +# Validates that a value does not contain HTML +# or other unsafe content that could lead to XSS. +# Relies on Rails HTML Sanitizer: +# https://github.com/rails/rails-html-sanitizer +# +# Example: +# +# class Group < ActiveRecord::Base +# validates :name, presence: true, html_safety: true +# end +# +class HtmlSafetyValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + return if value.blank? || safe_value?(value) + + record.errors.add(attribute, self.class.error_message) + end + + def self.error_message + _("cannot contain HTML/XML tags, including any word between angle brackets (<,>).") + end + + private + + # The `FullSanitizer` encodes ampersands as the HTML entity name. + # This isn't particularly necessary for preventing XSS so the ampersand + # is pre-encoded to avoid it being flagged in the comparison. + def safe_value?(text) + pre_encoded_text = text.gsub('&', '&') + Rails::Html::FullSanitizer.new.sanitize(pre_encoded_text) == pre_encoded_text + end +end diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml index 1aaf5883bf4..b4eda80201c 100644 --- a/app/views/import/bitbucket_server/status.html.haml +++ b/app/views/import/bitbucket_server/status.html.haml @@ -54,7 +54,7 @@ - @repos.each do |repo| %tr{ id: "repo_#{repo.project_key}___#{repo.slug}", data: { project: repo.project_key, repository: repo.slug } } %td - = link_to repo.browse_url, repo.browse_url, target: '_blank', rel: 'noopener noreferrer' + = sanitize(link_to(repo.browse_url, repo.browse_url, target: '_blank', rel: 'noopener noreferrer'), attributes: %w(href target rel)) %td.import-target %fieldset.row .input-group @@ -75,7 +75,7 @@ - @incompatible_repos.each do |repo| %tr{ id: "repo_#{repo.project_key}___#{repo.slug}" } %td - = link_to repo.browse_url, repo.browse_url, target: '_blank', rel: 'noopener noreferrer' + = sanitize(link_to(repo.browse_url, repo.browse_url, target: '_blank', rel: 'noopener noreferrer'), attributes: %w(href target rel)) %td.import-target %td.import-actions-job-status = label_tag 'Incompatible Project', nil, class: 'label badge-danger' diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml index 50bc4fb35df..d24b9fd1b95 100644 --- a/app/views/shared/notes/_note.html.haml +++ b/app/views/shared/notes/_note.html.haml @@ -32,7 +32,7 @@ .note-header-info %a{ href: user_path(note.author) } %span.note-header-author-name.bold - = sanitize(note.author.name) + = note.author.name = user_status(note.author) %span.note-headline-light = note.author.to_reference |