...@@ -2,6 +2,41 @@ ...@@ -2,6 +2,41 @@
documentation](doc/development/changelog.md) for instructions on adding your own documentation](doc/development/changelog.md) for instructions on adding your own
entry. entry.
## 11.8.4 (2019-03-26)
### Security (7 changes)
- Disallow guest users from accessing Releases.
- Fix PDF.js vulnerability.
- Hide "related branches" when user does not have permission.
- Fix XSS in resolve conflicts form.
- Added rake task for removing EXIF data from existing uploads.
- Disallow updating namespace when updating a project.
- Use UntrustedRegexp for matching refs policy.
## 11.8.3 (2019-03-19)
### Security (1 change)
- Remove project serialization in quick actions response.
## 11.8.2 (2019-03-13)
### Security (1 change)
- Fixed ability to see private groups by users not belonging to given group.
### Fixed (5 changes)
- Fix import_jid error on project import. !25239
- Properly handle multiple X-Forwarded-For addresses in runner IP. !25511
- Fix error when viewing group issue boards when user doesn't have explicit group permissions. !25524
- Fix method to mark a project repository as writable. !25546
- Allow project members to see private group if the project is in the group namespace.
## 11.8.1 (2019-02-28) ## 11.8.1 (2019-02-28)
### Security (21 changes) ### Security (21 changes)
... ...
......
8.3.1 8.3.2
11.8.1 11.8.4
...@@ -16,7 +16,9 @@ export default class Issue { ...@@ -16,7 +16,9 @@ export default class Issue {
Issue.createMrDropdownWrap = document.querySelector('.create-mr-dropdown-wrap'); Issue.createMrDropdownWrap = document.querySelector('.create-mr-dropdown-wrap');
Issue.initMergeRequests(); Issue.initMergeRequests();
if (document.querySelector('#related-branches')) {
Issue.initRelatedBranches(); Issue.initRelatedBranches();
}
this.closeButtons = $('a.btn-close'); this.closeButtons = $('a.btn-close');
this.reopenButtons = $('a.btn-reopen'); this.reopenButtons = $('a.btn-reopen');
... ...
......
...@@ -28,7 +28,7 @@ export default { ...@@ -28,7 +28,7 @@ export default {
}, },
watch: { pdf: 'load' }, watch: { pdf: 'load' },
mounted() { mounted() {
pdfjsLib.PDFJS.workerSrc = workerSrc; pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
if (this.hasPDF) this.load(); if (this.hasPDF) this.load();
}, },
methods: { methods: {
... ...
......
...@@ -54,7 +54,7 @@ module NotesActions ...@@ -54,7 +54,7 @@ module NotesActions
respond_to do |format| respond_to do |format|
format.json do format.json do
json = { json = {
commands_changes: @note.commands_changes commands_changes: @note.commands_changes&.slice(:emoji_award, :time_estimate, :spend_time)
} }
if @note.persisted? && return_discussion? if @note.persisted? && return_discussion?
... ...
......
...@@ -39,6 +39,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -39,6 +39,7 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_create_merge_request_from!, only: [:create_merge_request] before_action :authorize_create_merge_request_from!, only: [:create_merge_request]
before_action :authorize_import_issues!, only: [:import_csv] before_action :authorize_import_issues!, only: [:import_csv]
before_action :authorize_download_code!, only: [:related_branches]
before_action :set_suggested_issues_feature_flags, only: [:new] before_action :set_suggested_issues_feature_flags, only: [:new]
... ...
......
...@@ -47,7 +47,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -47,7 +47,7 @@ class ProjectsController < Projects::ApplicationController
end end
def create def create
@project = ::Projects::CreateService.new(current_user, project_params).execute @project = ::Projects::CreateService.new(current_user, project_params(attributes: project_params_create_attributes)).execute
if @project.saved? if @project.saved?
cookies[:issue_board_welcome_hidden] = { path: project_path(@project), value: nil, expires: Time.at(0) } cookies[:issue_board_welcome_hidden] = { path: project_path(@project), value: nil, expires: Time.at(0) }
...@@ -328,9 +328,9 @@ class ProjectsController < Projects::ApplicationController ...@@ -328,9 +328,9 @@ class ProjectsController < Projects::ApplicationController
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
def project_params def project_params(attributes: [])
params.require(:project) params.require(:project)
.permit(project_params_attributes) .permit(project_params_attributes + attributes)
end end
def project_params_attributes def project_params_attributes
...@@ -349,11 +349,10 @@ class ProjectsController < Projects::ApplicationController ...@@ -349,11 +349,10 @@ class ProjectsController < Projects::ApplicationController
:last_activity_at, :last_activity_at,
:lfs_enabled, :lfs_enabled,
:name, :name,
:namespace_id,
:only_allow_merge_if_all_discussions_are_resolved, :only_allow_merge_if_all_discussions_are_resolved,
:only_allow_merge_if_pipeline_succeeds, :only_allow_merge_if_pipeline_succeeds,
:printing_merge_request_link_enabled,
:path, :path,
:printing_merge_request_link_enabled,
:public_builds, :public_builds,
:request_access_enabled, :request_access_enabled,
:runners_token, :runners_token,
...@@ -375,6 +374,10 @@ class ProjectsController < Projects::ApplicationController ...@@ -375,6 +374,10 @@ class ProjectsController < Projects::ApplicationController
] ]
end end
def project_params_create_attributes
[:namespace_id]
end
def custom_import_params def custom_import_params
{} {}
end end
... ...
......
...@@ -126,6 +126,10 @@ class Label < ActiveRecord::Base ...@@ -126,6 +126,10 @@ class Label < ActiveRecord::Base
fuzzy_search(query, [:title, :description]) fuzzy_search(query, [:title, :description])
end end
def self.by_ids(ids)
where(id: ids)
end
def open_issues_count(user = nil) def open_issues_count(user = nil)
issues_count(user, state: 'opened') issues_count(user, state: 'opened')
end end
... ...
......
...@@ -178,7 +178,6 @@ class ProjectPolicy < BasePolicy ...@@ -178,7 +178,6 @@ class ProjectPolicy < BasePolicy
enable :read_cycle_analytics enable :read_cycle_analytics
enable :award_emoji enable :award_emoji
enable :read_pages_content enable :read_pages_content
enable :read_release
end end
# These abilities are not allowed to admins that are not members of the project, # These abilities are not allowed to admins that are not members of the project,
...@@ -204,6 +203,7 @@ class ProjectPolicy < BasePolicy ...@@ -204,6 +203,7 @@ class ProjectPolicy < BasePolicy
enable :read_deployment enable :read_deployment
enable :read_merge_request enable :read_merge_request
enable :read_sentry_issue enable :read_sentry_issue
enable :read_release
end end
# We define `:public_user_access` separately because there are cases in gitlab-ee # We define `:public_user_access` separately because there are cases in gitlab-ee
... ...
......
...@@ -70,10 +70,14 @@ class IssuableBaseService < BaseService ...@@ -70,10 +70,14 @@ class IssuableBaseService < BaseService
end end
def filter_labels def filter_labels
filter_labels_in_param(:add_label_ids) params[:add_label_ids] = labels_service.filter_labels_ids_in_param(:add_label_ids) if params[:add_label_ids]
filter_labels_in_param(:remove_label_ids) params[:remove_label_ids] = labels_service.filter_labels_ids_in_param(:remove_label_ids) if params[:remove_label_ids]
filter_labels_in_param(:label_ids)
find_or_create_label_ids if params[:label_ids]
params[:label_ids] = labels_service.filter_labels_ids_in_param(:label_ids)
elsif params[:labels]
params[:label_ids] = labels_service.find_or_create_by_titles.map(&:id)
end
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
...@@ -101,6 +105,10 @@ class IssuableBaseService < BaseService ...@@ -101,6 +105,10 @@ class IssuableBaseService < BaseService
end.compact end.compact
end end
def labels_service
@labels_service ||= ::Labels::AvailableLabelsService.new(current_user, parent, params)
end
def process_label_ids(attributes, existing_label_ids: nil) def process_label_ids(attributes, existing_label_ids: nil)
label_ids = attributes.delete(:label_ids) label_ids = attributes.delete(:label_ids)
add_label_ids = attributes.delete(:add_label_ids) add_label_ids = attributes.delete(:add_label_ids)
...@@ -118,10 +126,6 @@ class IssuableBaseService < BaseService ...@@ -118,10 +126,6 @@ class IssuableBaseService < BaseService
new_label_ids new_label_ids
end end
def available_labels
@available_labels ||= LabelsFinder.new(current_user, project_id: @project.id, include_ancestor_groups: true).execute
end
def handle_quick_actions_on_create(issuable) def handle_quick_actions_on_create(issuable)
merge_quick_actions_into_params!(issuable) merge_quick_actions_into_params!(issuable)
end end
... ...
......
# frozen_string_literal: true
module Labels
class AvailableLabelsService
attr_reader :current_user, :parent, :params
def initialize(current_user, parent, params)
@current_user = current_user
@parent = parent
@params = params
end
def find_or_create_by_titles
labels = params.delete(:labels)
return [] unless labels
labels = labels.split(',') if labels.is_a?(String)
labels.map do |label_name|
label = Labels::FindOrCreateService.new(
current_user,
parent,
include_ancestor_groups: true,
title: label_name.strip,
available_labels: available_labels
).execute
label
end.compact
end
def filter_labels_ids_in_param(key)
return [] if params[key].to_a.empty?
# rubocop:disable CodeReuse/ActiveRecord
available_labels.by_ids(params[key]).pluck(:id)
# rubocop:enable CodeReuse/ActiveRecord
end
private
def available_labels
@available_labels ||= LabelsFinder.new(current_user, finder_params).execute
end
def finder_params
params = { include_ancestor_groups: true }
case parent
when Group
params[:group_id] = parent.id
params[:only_group_labels] = true
when Project
params[:project_id] = parent.id
end
params
end
end
end
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
#merge-requests{ data: { url: referenced_merge_requests_project_issue_path(@project, @issue) } } #merge-requests{ data: { url: referenced_merge_requests_project_issue_path(@project, @issue) } }
// This element is filled in using JavaScript. // This element is filled in using JavaScript.
- if can?(current_user, :download_code, @project)
#related-branches{ data: { url: related_branches_project_issue_path(@project, @issue) } } #related-branches{ data: { url: related_branches_project_issue_path(@project, @issue) } }
// This element is filled in using JavaScript. // This element is filled in using JavaScript.
... ...
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.form-group.row .form-group.row
.col-md-4 .col-md-4
%h4= _('Resolve conflicts on source branch') %h4= _('Resolve conflicts on source branch')
.resolve-info .resolve-info{ "v-pre": true }
= translation.html_safe = translation.html_safe
.col-md-8 .col-md-8
%label.label-bold{ "for" => "commit-message" } %label.label-bold{ "for" => "commit-message" }
... ...
......
---
title: Fix import_jid error on project import
merge_request: 25239
author:
type: fixed
---
title: Fix error when viewing group issue boards when user doesn't have explicit group
permissions
merge_request: 25524
author:
type: fixed
---
title: Fix method to mark a project repository as writable
merge_request: 25546
author:
type: fixed
---
title: Allow project members to see private group if the project is in the group namespace
merge_request:
author:
type: fixed
---
title: Properly handle multiple X-Forwarded-For addresses in runner IP
merge_request: 25511
author:
type: fixed
# Uploads Sanitize tasks
## Requirements
You need `exiftool` installed on your system. If you installed GitLab:
- Using the Omnibus package, you're all set.
- From source, make sure `exiftool` is installed:
```sh
# Debian/Ubuntu
sudo apt-get install libimage-exiftool-perl
# RHEL/CentOS
sudo yum install perl-Image-ExifTool
```
## Remove EXIF data from existing uploads
Since 11.9 EXIF data are automatically stripped from JPG or TIFF image uploads.
Because EXIF data may contain sensitive information (e.g. GPS location), you
can remove EXIF data also from existing images which were uploaded before
with the following command:
```bash
sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:sanitize:remove_exif
```
This command by default runs in dry mode and it doesn't remove EXIF data. It can be used for
checking if (and how many) images should be sanitized.
The rake task accepts following parameters.
Parameter | Type | Description
--------- | ---- | -----------
`start_id` | integer | Only uploads with equal or greater ID will be processed
`stop_id` | integer | Only uploads with equal or smaller ID will be processed
`dry_run` | boolean | Do not remove EXIF data, only check if EXIF data are present or not, default: true
`sleep_time` | float | Pause for number of seconds after processing each image, default: 0.3 seconds
If you have too many uploads, you can speed up sanitization by setting
`sleep_time` to a lower value or by running multiple rake tasks in parallel,
each with a separate range of upload IDs (by setting `start_id` and `stop_id`).
To run the command without dry mode and remove EXIF data from all uploads, you can use:
```bash
sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:sanitize:remove_exif[,,false,] 2>&1 | tee exif.log
```
To run the command without dry mode on uploads with ID between 100 and 5000 and pause for 0.1 second, you can use:
```bash
sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:sanitize:remove_exif[100,5000,false,0.1] 2>&1 | tee exif.log
```
Because the output of commands will be probably long, the output is written also into exif.log file.
If sanitization fails for an upload, an error message should be in the output of the rake task (typical reasons may
be that the file is missing in the storage or it's not a valid image). Please
[report](https://gitlab.com/gitlab-org/gitlab-ce/issues/new) any issues at `gitlab.com` and use
prefix 'EXIF' in issue title with the error output and (if possible) the image.