Skip to content
Snippets Groups Projects
Commit 62f3248f authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/security/gitlab@12-5-stable-ee

parent 586bb7dc
No related branches found
No related tags found
No related merge requests found
Showing
with 125 additions and 28 deletions
Loading
Loading
@@ -64,7 +64,7 @@ gem 'u2f', '~> 0.2.1'
 
# GitLab Pages
gem 'validates_hostname', '~> 1.0.6'
gem 'rubyzip', '~> 1.3.0', require: 'zip'
gem 'rubyzip', '~> 2.0.0', require: 'zip'
# GitLab Pages letsencrypt support
gem 'acme-client', '~> 2.0.2'
 
Loading
Loading
@@ -141,7 +141,7 @@ gem 'gitlab-markup', '~> 1.7.0'
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
gem 'commonmarker', '~> 0.17'
gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~> 6.0'
gem 'rdoc', '~> 6.1.2'
gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
Loading
Loading
Loading
Loading
@@ -262,7 +262,7 @@ GEM
et-orbi (1.2.1)
tzinfo
eventmachine (1.2.7)
excon (0.62.0)
excon (0.71.1)
execjs (2.6.0)
expression_parser (0.9.0)
extended-markdown-filter (0.6.0)
Loading
Loading
@@ -760,7 +760,8 @@ GEM
rack (>= 0.4)
rack-attack (6.2.0)
rack (>= 1.0, < 3)
rack-cors (1.0.2)
rack-cors (1.0.6)
rack (>= 1.6.0)
rack-oauth2 (1.9.3)
activesupport
attr_required
Loading
Loading
@@ -817,7 +818,7 @@ GEM
ffi (>= 1.0.6)
msgpack (>= 0.4.3)
optimist (>= 3.0.0)
rdoc (6.0.4)
rdoc (6.1.2)
re2 (1.1.1)
recaptcha (4.13.1)
json
Loading
Loading
@@ -926,7 +927,7 @@ GEM
sexp_processor (~> 4.9)
rubyntlm (0.6.2)
rubypants (0.2.0)
rubyzip (1.3.0)
rubyzip (2.0.0)
rugged (0.28.3.1)
safe_yaml (1.0.4)
sanitize (4.6.6)
Loading
Loading
@@ -1295,7 +1296,7 @@ DEPENDENCIES
raindrops (~> 0.18)
rblineprof (~> 0.3.6)
rbtrace (~> 0.4)
rdoc (~> 6.0)
rdoc (~> 6.1.2)
re2 (~> 1.1.1)
recaptcha (~> 4.11)
redis (~> 4.0)
Loading
Loading
@@ -1319,7 +1320,7 @@ DEPENDENCIES
ruby-prof (~> 1.0.0)
ruby-progressbar
ruby_parser (~> 3.8)
rubyzip (~> 1.3.0)
rubyzip (~> 2.0.0)
rugged (~> 0.28)
sanitize (~> 4.6)
sassc-rails (~> 2.1.0)
Loading
Loading
Loading
Loading
@@ -5,7 +5,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../event_hub';
import store from '../store/';
import { FREQUENT_ITEMS, STORAGE_KEY } from '../constants';
import { isMobile, updateExistingFrequentItem } from '../utils';
import { isMobile, updateExistingFrequentItem, sanitizeItem } from '../utils';
import FrequentItemsSearchInput from './frequent_items_search_input.vue';
import FrequentItemsList from './frequent_items_list.vue';
import frequentItemsMixin from './frequent_items_mixin';
Loading
Loading
@@ -64,7 +64,9 @@ export default {
this.fetchFrequentItems();
}
},
logItemAccess(storageKey, item) {
logItemAccess(storageKey, unsanitizedItem) {
const item = sanitizeItem(unsanitizedItem);
if (!AccessorUtilities.isLocalStorageAccessSafe()) {
return false;
}
Loading
Loading
<script>
import FrequentItemsListItem from './frequent_items_list_item.vue';
import frequentItemsMixin from './frequent_items_mixin';
import { sanitizeItem } from '../utils';
 
export default {
components: {
Loading
Loading
@@ -48,6 +49,9 @@ export default {
? this.translations.itemListErrorMessage
: this.translations.itemListEmptyMessage;
},
sanitizedItems() {
return this.items.map(sanitizeItem);
},
},
};
</script>
Loading
Loading
@@ -59,7 +63,7 @@ export default {
{{ listEmptyMessage }}
</li>
<frequent-items-list-item
v-for="item in items"
v-for="item in sanitizedItems"
v-else
:key="item.id"
:item-id="item.id"
Loading
Loading
import _ from 'underscore';
import bp from '~/breakpoints';
import sanitize from 'sanitize-html';
import { FREQUENT_ITEMS, HOUR_IN_MS } from './constants';
 
export const isMobile = () => {
Loading
Loading
@@ -47,3 +48,9 @@ export const updateExistingFrequentItem = (frequentItem, item) => {
lastAccessedOn: accessedOverHourAgo ? Date.now() : frequentItem.lastAccessedOn,
};
};
export const sanitizeItem = item => ({
...item,
name: sanitize(item.name.toString(), { allowedTags: [] }),
namespace: sanitize(item.namespace.toString(), { allowedTags: [] }),
});
import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import Api from './api';
import { escape } from 'lodash';
import { normalizeHeaders } from './lib/utils/common_utils';
import { __ } from '~/locale';
 
Loading
Loading
@@ -75,10 +76,12 @@ const groupsSelect = () => {
}
},
formatResult(object) {
return `<div class='group-result'> <div class='group-name'>${object.full_name}</div> <div class='group-path'>${object.full_path}</div> </div>`;
return `<div class='group-result'> <div class='group-name'>${escape(
object.full_name,
)}</div> <div class='group-path'>${object.full_path}</div> </div>`;
},
formatSelection(object) {
return object.full_name;
return escape(object.full_name);
},
dropdownCssClass: 'ajax-groups-dropdown select2-infinite',
// we do not want to escape markup since we are displaying html in results
Loading
Loading
Loading
Loading
@@ -5,6 +5,7 @@ require 'fogbugz'
 
class ApplicationController < ActionController::Base
include Gitlab::GonHelper
include Gitlab::NoCacheHeaders
include GitlabRoutingHelper
include PageLayoutHelper
include SafeParamsHelper
Loading
Loading
@@ -54,7 +55,6 @@ class ApplicationController < ActionController::Base
# Adds `no-store` to the DEFAULT_CACHE_CONTROL, to prevent security
# concerns due to caching private data.
DEFAULT_GITLAB_CACHE_CONTROL = "#{ActionDispatch::Http::Cache::Response::DEFAULT_CACHE_CONTROL}, no-store"
DEFAULT_GITLAB_CONTROL_NO_CACHE = "#{DEFAULT_GITLAB_CACHE_CONTROL}, no-cache"
 
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
Loading
Loading
@@ -238,9 +238,9 @@ class ApplicationController < ActionController::Base
end
 
def no_cache_headers
headers['Cache-Control'] = DEFAULT_GITLAB_CONTROL_NO_CACHE
headers['Pragma'] = 'no-cache' # HTTP 1.0 compatibility
headers['Expires'] = 'Fri, 01 Jan 1990 00:00:00 GMT'
DEFAULT_GITLAB_NO_CACHE_HEADERS.each do |k, v|
headers[k] = v
end
end
 
def default_headers
Loading
Loading
Loading
Loading
@@ -19,7 +19,7 @@ class DashboardController < Dashboard::ApplicationController
 
format.json do
load_events
pager_json("events/_events", @events.count)
pager_json('events/_events', @events.count { |event| event.visible_to_user?(current_user) })
end
end
end
Loading
Loading
@@ -37,6 +37,7 @@ class DashboardController < Dashboard::ApplicationController
@events = EventCollection
.new(projects, offset: params[:offset].to_i, filter: event_filter)
.to_a
.map(&:present)
 
Events::RenderService.new(current_user).execute(@events)
end
Loading
Loading
Loading
Loading
@@ -91,7 +91,7 @@ class GroupsController < Groups::ApplicationController
 
format.json do
load_events
pager_json("events/_events", @events.count)
pager_json("events/_events", @events.count { |event| event.visible_to_user?(current_user) })
end
end
end
Loading
Loading
@@ -208,8 +208,9 @@ class GroupsController < Groups::ApplicationController
.includes(:namespace)
 
@events = EventCollection
.new(projects, offset: params[:offset].to_i, filter: event_filter, groups: groups)
.to_a
.new(projects, offset: params[:offset].to_i, filter: event_filter, groups: groups)
.to_a
.map(&:present)
 
Events::RenderService
.new(current_user)
Loading
Loading
Loading
Loading
@@ -116,7 +116,7 @@ class ProjectsController < Projects::ApplicationController
format.html
format.json do
load_events
pager_json('events/_events', @events.count)
pager_json('events/_events', @events.count { |event| event.visible_to_user?(current_user) })
end
end
end
Loading
Loading
@@ -337,6 +337,7 @@ class ProjectsController < Projects::ApplicationController
@events = EventCollection
.new(projects, offset: params[:offset].to_i, filter: event_filter)
.to_a
.map(&:present)
 
Events::RenderService.new(current_user).execute(@events, atom_request: request.format.atom?)
end
Loading
Loading
Loading
Loading
@@ -365,8 +365,8 @@ module ProjectsHelper
@project.grafana_integration&.grafana_url
end
 
def grafana_integration_token
@project.grafana_integration&.token
def grafana_integration_masked_token
@project.grafana_integration&.masked_token
end
 
def grafana_integration_enabled?
Loading
Loading
# frozen_string_literal: true
 
class GenericCommitStatus < CommitStatus
EXTERNAL_STAGE_IDX = 1_000_000
before_validation :set_default_values
 
validates :target_url, addressable_url: true,
length: { maximum: 255 },
allow_nil: true
validate :name_uniqueness_across_types, unless: :importing?
 
# GitHub compatible API
alias_attribute :context, :name
Loading
Loading
@@ -13,7 +16,7 @@ class GenericCommitStatus < CommitStatus
def set_default_values
self.context ||= 'default'
self.stage ||= 'external'
self.stage_idx ||= 1000000
self.stage_idx ||= EXTERNAL_STAGE_IDX
end
 
def tags
Loading
Loading
@@ -25,4 +28,14 @@ class GenericCommitStatus < CommitStatus
.new(self, current_user)
.fabricate!
end
private
def name_uniqueness_across_types
return if !pipeline || name.blank?
if pipeline.statuses.where(name: name).where.not(type: type).exists?
errors.add(:name, :taken)
end
end
end
Loading
Loading
@@ -8,11 +8,13 @@ class GrafanaIntegration < ApplicationRecord
algorithm: 'aes-256-gcm',
key: Settings.attr_encrypted_db_key_base_32
 
before_validation :check_token_changes
validates :grafana_url,
length: { maximum: 1024 },
addressable_url: { enforce_sanitization: true, ascii_only: true }
 
validates :token, :project, presence: true
validates :encrypted_token, :project, presence: true
 
validates :enabled, inclusion: { in: [true, false] }
 
Loading
Loading
@@ -23,4 +25,28 @@ class GrafanaIntegration < ApplicationRecord
 
@client ||= ::Grafana::Client.new(api_url: grafana_url.chomp('/'), token: token)
end
def masked_token
mask(encrypted_token)
end
def masked_token_was
mask(encrypted_token_was)
end
private
def token
decrypt(:token, encrypted_token)
end
def check_token_changes
return unless [encrypted_token_was, masked_token_was].include?(token)
clear_attribute_changes [:token, :encrypted_token, :encrypted_token_iv]
end
def mask(token)
token&.squish&.gsub(/./, '*')
end
end
Loading
Loading
@@ -537,7 +537,8 @@ class Note < ApplicationRecord
# if they are not equal, then there are private/confidential references as well
user_visible_reference_count > 0 && user_visible_reference_count == total_reference_count
else
referenced_mentionables(user).any?
refs = all_references(user)
refs.all.any? && refs.stateful_not_visible_counter == 0
end
end
 
Loading
Loading
Loading
Loading
@@ -2274,6 +2274,10 @@ class Project < ApplicationRecord
end
end
 
def template_source?
false
end
private
 
def closest_namespace_setting(name)
Loading
Loading
Loading
Loading
@@ -21,6 +21,14 @@ class BasePolicy < DeclarativePolicy::Base
with_options scope: :user, score: 0
condition(:deactivated) { @user&.deactivated? }
 
desc "User email is unconfirmed or user account is locked"
with_options scope: :user, score: 0
condition(:inactive) do
Feature.enabled?(:inactive_policy_condition, default_enabled: true) &&
@user &&
!@user&.active_for_authentication?
end
with_options scope: :user, score: 0
condition(:external_user) { @user.nil? || @user.external? }
 
Loading
Loading
Loading
Loading
@@ -36,6 +36,13 @@ class GlobalPolicy < BasePolicy
enable :use_slash_commands
end
 
rule { inactive }.policy do
prevent :log_in
prevent :access_api
prevent :access_git
prevent :use_slash_commands
end
rule { blocked | internal }.policy do
prevent :log_in
prevent :access_api
Loading
Loading
Loading
Loading
@@ -3,6 +3,18 @@
class EventPresenter < Gitlab::View::Presenter::Delegated
presents :event
 
def initialize(subject, **attributes)
super
@visible_to_user_cache = ActiveSupport::Cache::MemoryStore.new
end
# Caching `visible_to_user?` method in the presenter beause it might be called multiple times.
def visible_to_user?(user = nil)
@visible_to_user_cache.fetch(user&.id) { super(user) }
end
# implement cache here
def resource_parent_name
resource_parent&.full_name || ''
end
Loading
Loading
Loading
Loading
@@ -18,7 +18,7 @@ class CompareService
return unless raw_compare && raw_compare.base && raw_compare.head
 
Compare.new(raw_compare,
target_project,
start_project,
base_sha: base_sha,
straight: straight)
end
Loading
Loading
Loading
Loading
@@ -6,6 +6,12 @@ module Projects
def execute(group_link)
return false unless group_link
 
if group_link.project.private?
TodosDestroyer::ProjectPrivateWorker.perform_in(Todo::WAIT_FOR_DELETE, project.id)
else
TodosDestroyer::ConfidentialIssueWorker.perform_in(Todo::WAIT_FOR_DELETE, nil, project.id)
end
group_link.destroy
end
end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment