diff --git a/CHANGELOG.md b/CHANGELOG.md index a980e2ae2e..d76689211a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,25 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 14.8.6 (2022-04-29) + +### Security (14 changes) + +- [Update Import/Export merge/push access levels & exclude ci config path](gitlab-org/security/gitlab@abfa8d4c128316b1ba095ff8eda7e86018e47caf) ([merge request](gitlab-org/security/gitlab!2372)) +- [Prevent maintainers from editing PipelineSchedule](gitlab-org/security/gitlab@761a7777cb480d02b9c3418aa7317eba7c0eaff1) ([merge request](gitlab-org/security/gitlab!2423)) +- [Add validation to pypi file sha256 values](gitlab-org/security/gitlab@712cc01aee2be4b6a9847746a080f190041367d5) ([merge request](gitlab-org/security/gitlab!2417)) +- [Conan Token uses PAT rather than ID in payload](gitlab-org/security/gitlab@ba3070c90dd1b575982df22c256b0e3f97a9e919) ([merge request](gitlab-org/security/gitlab!2346)) +- [[security] Fix markdown API disclosing issue titles of limited projects](gitlab-org/security/gitlab@fd3cb263e8f165a4a1a7894c08ddf254f9cf1e92) ([merge request](gitlab-org/security/gitlab!2405)) +- [Verify that mentioned user can read TODO's note](gitlab-org/security/gitlab@e54be58cc79011d7c79dae94b993774ab36ef232) ([merge request](gitlab-org/security/gitlab!2398)) +- [Invalidate markdown cache to clear up stored XSS](gitlab-org/security/gitlab@160cdda98c80e052abbb4bec226ad63fe9c9e403) ([merge request](gitlab-org/security/gitlab!2420)) +- [Allow rate limiting of deploy tokens](gitlab-org/security/gitlab@78f7ee3d7e1258375ddcea3a20e3798092e89d41) ([merge request](gitlab-org/security/gitlab!2385)) +- [Add suffix to cache name to add isolation](gitlab-org/security/gitlab@184d49640f5dcc4ac1522c874a7b5e0c16d2e05f) ([merge request](gitlab-org/security/gitlab!2373)) +- [Disable wiki access with CI_JOB_TOKEN when improper access level](gitlab-org/security/gitlab@db93d134394675a4335c92557a55ac4381ed303f) ([merge request](gitlab-org/security/gitlab!2391)) +- [Sanitize error input to prevent HTML/CSS injection in messages](gitlab-org/security/gitlab@333dd602091810639912702c80034468ff6f8aa0) ([merge request](gitlab-org/security/gitlab!2378)) +- [Secure debug trace artifact download](gitlab-org/security/gitlab@266d812ba2e8e9936269323465c867983e3a2ebf) ([merge request](gitlab-org/security/gitlab!2367)) +- [Use password type for all secret integration properties](gitlab-org/security/gitlab@eda2b8f02b34ead354ef07b9e41be006cf90f51b) ([merge request](gitlab-org/security/gitlab!2411)) +- [Limit CI job group_name regexp](gitlab-org/security/gitlab@03ab6e9f312fb6fe50a6361f7bc78d527b223b96) ([merge request](gitlab-org/security/gitlab!2381)) + ## 14.8.5 (2022-03-31) ### Security (21 changes) diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 8d7e6ce0fe..a40c7d8994 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -14.8.5 \ No newline at end of file +14.8.6 \ No newline at end of file diff --git a/VERSION b/VERSION index 8d7e6ce0fe..a40c7d8994 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -14.8.5 \ No newline at end of file +14.8.6 \ No newline at end of file diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index 7a03e7b84b..2be97fa6d4 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -29,6 +29,25 @@ class Projects::ApplicationController < ApplicationController @project = find_routable!(Project, path, request.fullpath, extra_authorization_proc: auth_proc) end + def auth_proc + ->(project) { !project.pending_delete? } + end + + def authorize_read_build_trace! + return if can?(current_user, :read_build_trace, build) + + if build.debug_mode? + access_denied!( + _('You must have developer or higher permissions in the associated project to view job logs when debug trace ' \ + "is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline " \ + 'configuration or CI/CD settings. If you need to view this job log, a project maintainer must add you to ' \ + 'the project with developer permissions or higher.') + ) + else + access_denied!(_('The current user is not authorized to access the job log.')) + end + end + def build_canonical_path(project) params[:namespace_id] = project.namespace.to_param params[:project_id] = project.to_param diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 7bb3ed1d10..04d4bc8f4e 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -7,6 +7,7 @@ class Projects::ArtifactsController < Projects::ApplicationController layout 'project' before_action :authorize_read_build! + before_action :authorize_read_build_trace!, only: [:download] before_action :authorize_update_build!, only: [:keep] before_action :authorize_destroy_artifacts!, only: [:destroy] before_action :extract_ref_name_and_path @@ -162,4 +163,10 @@ class Projects::ArtifactsController < Projects::ApplicationController render_404 unless @entry.exists? end + + def authorize_read_build_trace! + return unless params[:file_type] == 'trace' + + super + end end diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index bfc2fe6432..8146308aa9 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -171,17 +171,7 @@ class Projects::JobsController < Projects::ApplicationController private - def authorize_read_build_trace! - return if can?(current_user, :read_build_trace, @build) - - msg = _( - "You must have developer or higher permissions in the associated project to view job logs when debug trace is enabled. To disable debug trace, set the 'CI_DEBUG_TRACE' variable to 'false' in your pipeline configuration or CI/CD settings. " \ - "If you need to view this job log, a project maintainer must add you to the project with developer permissions or higher." - ) - return access_denied!(msg) if @build.debug_mode? - - access_denied!(_('The current user is not authorized to access the job log.')) - end + attr_reader :build def authorize_update_build! return access_denied! unless can?(current_user, :update_build, @build) diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index ac94cc001d..f617140366 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -7,7 +7,8 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController before_action :authorize_play_pipeline_schedule!, only: [:play] before_action :authorize_read_pipeline_schedule! before_action :authorize_create_pipeline_schedule!, only: [:new, :create] - before_action :authorize_update_pipeline_schedule!, except: [:index, :new, :create, :play] + before_action :authorize_update_pipeline_schedule!, only: [:edit, :update] + before_action :authorize_take_ownership_pipeline_schedule!, only: [:take_ownership] before_action :authorize_admin_pipeline_schedule!, only: [:destroy] feature_category :continuous_integration @@ -108,6 +109,10 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController return access_denied! unless can?(current_user, :update_pipeline_schedule, schedule) end + def authorize_take_ownership_pipeline_schedule! + return access_denied! unless can?(current_user, :take_ownership_pipeline_schedule, schedule) + end + def authorize_admin_pipeline_schedule! return access_denied! unless can?(current_user, :admin_pipeline_schedule, schedule) end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index c4d1a2c740..ad5a9ab0ff 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -895,7 +895,10 @@ module Ci end end - cache + type_suffix = pipeline.protected_ref? ? 'protected' : 'non_protected' + cache.map do |entry| + entry.merge(key: "#{entry[:key]}-#{type_suffix}") + end end def credentials diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 21e2e21e9b..5bddf45341 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -229,7 +229,13 @@ class CommitStatus < Ci::ApplicationRecord end def group_name - name.to_s.sub(%r{([\b\s:]+((\[.*\])|(\d+[\s:\/\\]+\d+)))+\s*\z}, '').strip + # [\b\s:] -> whitespace or column + # (\[.*\])|(\d+[\s:\/\\]+\d+) -> variables/matrix or parallel-jobs numbers + # {1,3} -> number of times that matches the variables/matrix or parallel-jobs numbers + # we limit this to 3 because of possible abuse + regex = %r{([\b\s:]+((\[.*\])|(\d+[\s:\/\\]+\d+))){1,3}\s*\z} + + name.to_s.sub(regex, '').strip end def failed_but_allowed? diff --git a/app/models/integrations/asana.rb b/app/models/integrations/asana.rb index acce2d9879..5d9373aa31 100644 --- a/app/models/integrations/asana.rb +++ b/app/models/integrations/asana.rb @@ -29,10 +29,12 @@ module Integrations def fields [ { - type: 'text', + type: 'password', name: 'api_key', title: 'API key', help: s_('AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user.'), + non_empty_password_title: s_('ProjectService|Enter new API key'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current API key.'), # Example Personal Access Token from Asana docs placeholder: '0/68a9e79b868c6789e79a124c30b0', required: true diff --git a/app/models/integrations/assembla.rb b/app/models/integrations/assembla.rb index 6a36045330..ccd24c1fb2 100644 --- a/app/models/integrations/assembla.rb +++ b/app/models/integrations/assembla.rb @@ -19,8 +19,19 @@ module Integrations def fields [ - { type: 'text', name: 'token', placeholder: '', required: true }, - { type: 'text', name: 'subdomain', placeholder: '' } + { + type: 'password', + name: 'token', + non_empty_password_title: s_('ProjectService|Enter new token'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), + placeholder: '', + required: true + }, + { + type: 'text', + name: 'subdomain', + placeholder: '' + } ] end diff --git a/app/models/integrations/bamboo.rb b/app/models/integrations/bamboo.rb index 57767c63cf..eaf1992f92 100644 --- a/app/models/integrations/bamboo.rb +++ b/app/models/integrations/bamboo.rb @@ -55,10 +55,12 @@ module Integrations required: true }, { - type: 'text', + type: 'password', name: 'build_key', - placeholder: s_('KEY'), help: s_('BambooService|Bamboo build plan key.'), + non_empty_password_title: s_('BambooService|Enter new build key'), + non_empty_password_help: s_('BambooService|Leave blank to use your current build key.'), + placeholder: s_('KEY'), required: true }, { diff --git a/app/models/integrations/base_slash_commands.rb b/app/models/integrations/base_slash_commands.rb index 1d271e75a9..a0ac547489 100644 --- a/app/models/integrations/base_slash_commands.rb +++ b/app/models/integrations/base_slash_commands.rb @@ -26,7 +26,13 @@ module Integrations def fields [ - { type: 'text', name: 'token', placeholder: 'XXxxXXxxXXxxXXxxXXxxXXxx' } + { + type: 'password', + name: 'token', + non_empty_password_title: s_('ProjectService|Enter new token'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), + placeholder: 'XXxxXXxxXXxxXXxxXXxxXXxx' + } ] end diff --git a/app/models/integrations/buildkite.rb b/app/models/integrations/buildkite.rb index 90593d78a5..5b1ec9b851 100644 --- a/app/models/integrations/buildkite.rb +++ b/app/models/integrations/buildkite.rb @@ -76,10 +76,12 @@ module Integrations def fields [ - { type: 'text', + { type: 'password', name: 'token', title: _('Token'), help: s_('ProjectService|The token you get after you create a Buildkite pipeline with a GitLab repository.'), + non_empty_password_title: s_('ProjectService|Enter new token'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), required: true }, { type: 'text', diff --git a/app/models/integrations/campfire.rb b/app/models/integrations/campfire.rb index c78fc6eff5..9aa86136c9 100644 --- a/app/models/integrations/campfire.rb +++ b/app/models/integrations/campfire.rb @@ -27,11 +27,13 @@ module Integrations def fields [ { - type: 'text', + type: 'password', name: 'token', title: _('Campfire token'), - placeholder: '', help: s_('CampfireService|API authentication token from Campfire.'), + non_empty_password_title: s_('ProjectService|Enter new token'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), + placeholder: '', required: true }, { diff --git a/app/models/integrations/drone_ci.rb b/app/models/integrations/drone_ci.rb index 3c18e5d873..73f78bec38 100644 --- a/app/models/integrations/drone_ci.rb +++ b/app/models/integrations/drone_ci.rb @@ -96,8 +96,21 @@ module Integrations def fields [ - { type: 'text', name: 'token', help: s_('ProjectService|Token for the Drone project.'), required: true }, - { type: 'text', name: 'drone_url', title: s_('ProjectService|Drone server URL'), placeholder: 'http://drone.example.com', required: true } + { + type: 'password', + name: 'token', + help: s_('ProjectService|Token for the Drone project.'), + non_empty_password_title: s_('ProjectService|Enter new token'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), + required: true + }, + { + type: 'text', + name: 'drone_url', + title: s_('ProjectService|Drone server URL'), + placeholder: 'http://drone.example.com', + required: true + } ] end diff --git a/app/models/integrations/flowdock.rb b/app/models/integrations/flowdock.rb index 443f61e65d..cfb7a02b75 100644 --- a/app/models/integrations/flowdock.rb +++ b/app/models/integrations/flowdock.rb @@ -26,7 +26,15 @@ module Integrations def fields [ - { type: 'text', name: 'token', placeholder: s_('FlowdockService|1b609b52537...'), required: true, help: 'Enter your Flowdock token.' } + { + type: 'password', + name: 'token', + help: s_('FlowdockService|Enter your Flowdock token.'), + non_empty_password_title: s_('ProjectService|Enter new token'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), + placeholder: '1b609b52537...', + required: true + } ] end diff --git a/app/models/integrations/packagist.rb b/app/models/integrations/packagist.rb index f616bc5faf..738319ce83 100644 --- a/app/models/integrations/packagist.rb +++ b/app/models/integrations/packagist.rb @@ -36,10 +36,12 @@ module Integrations required: true }, { - type: 'text', + type: 'password', name: 'token', title: _('Token'), help: s_('Enter your Packagist token.'), + non_empty_password_title: s_('ProjectService|Enter new token'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), placeholder: '', required: true }, diff --git a/app/models/integrations/pivotaltracker.rb b/app/models/integrations/pivotaltracker.rb index 24cfd51eb5..883d798829 100644 --- a/app/models/integrations/pivotaltracker.rb +++ b/app/models/integrations/pivotaltracker.rb @@ -28,9 +28,11 @@ module Integrations def fields [ { - type: 'text', + type: 'password', name: 'token', help: s_('PivotalTrackerService|Pivotal Tracker API token. User must have access to the story. All comments are attributed to this user.'), + non_empty_password_title: s_('ProjectService|Enter new token'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), required: true }, { diff --git a/app/models/integrations/pushover.rb b/app/models/integrations/pushover.rb index db39a4c68b..7fd5efa876 100644 --- a/app/models/integrations/pushover.rb +++ b/app/models/integrations/pushover.rb @@ -22,18 +22,22 @@ module Integrations def fields [ { - type: 'text', + type: 'password', name: 'api_key', title: _('API key'), help: s_('PushoverService|Enter your application key.'), + non_empty_password_title: s_('ProjectService|Enter new API key'), + non_empty_password_help: s_('ProjectService|Leave blank to use your current API key.'), placeholder: '', required: true }, { - type: 'text', + type: 'password', name: 'user_key', title: _('User key'), help: s_('PushoverService|Enter your user key.'), + non_empty_password_title: s_('PushoverService|Enter new user key'), + non_empty_password_help: s_('PushoverService|Leave blank to use your current user key.'), placeholder: '', required: true }, diff --git a/app/models/issue.rb b/app/models/issue.rb index 68ea6cb3ab..6a1f26a68b 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -630,7 +630,8 @@ class Issue < ApplicationRecord # Returns `true` if this Issue is visible to everybody. def publicly_visible? - project.public? && !confidential? && !hidden? && !::Gitlab::ExternalAuthorization.enabled? + project.public? && project.feature_available?(:issues, nil) && + !confidential? && !hidden? && !::Gitlab::ExternalAuthorization.enabled? end def expire_etag_cache diff --git a/app/models/packages/package_file.rb b/app/models/packages/package_file.rb index fc7c348dfd..bd250caca7 100644 --- a/app/models/packages/package_file.rb +++ b/app/models/packages/package_file.rb @@ -35,6 +35,7 @@ class Packages::PackageFile < ApplicationRecord validates :file_name, presence: true validates :file_name, uniqueness: { scope: :package }, if: -> { package&.pypi? } + validates :file_sha256, format: { with: Gitlab::Regex.sha256_regex }, if: -> { package&.pypi? }, allow_nil: true scope :recent, -> { order(id: :desc) } scope :limit_recent, ->(limit) { recent.limit(limit) } diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb index 0d3e50837a..30bca435a2 100644 --- a/app/models/project_feature.rb +++ b/app/models/project_feature.rb @@ -104,7 +104,7 @@ class ProjectFeature < ApplicationRecord # that the user has access to the feature. It's important to use this scope with others # that checks project authorizations first (e.g. `filter_by_feature_visibility`). # - # This method uses an optimised version of `with_feature_access_level` for + # This method uses an optimized version of `with_feature_access_level` for # logged in users to more efficiently get private projects with the given # feature. def self.with_feature_available_for_user(feature, user) diff --git a/app/policies/ci/pipeline_schedule_policy.rb b/app/policies/ci/pipeline_schedule_policy.rb index 2ef5ffd6a5..3a674bfef9 100644 --- a/app/policies/ci/pipeline_schedule_policy.rb +++ b/app/policies/ci/pipeline_schedule_policy.rb @@ -15,11 +15,14 @@ module Ci rule { can?(:create_pipeline) }.enable :play_pipeline_schedule rule { can?(:admin_pipeline) | (can?(:update_build) & owner_of_schedule) }.policy do - enable :update_pipeline_schedule enable :admin_pipeline_schedule enable :read_pipeline_schedule_variables end + rule { admin | (owner_of_schedule & can?(:update_build)) }.policy do + enable :update_pipeline_schedule + end + rule { can?(:admin_pipeline_schedule) & ~owner_of_schedule }.policy do enable :take_ownership_pipeline_schedule end diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb index 091f441831..6c6ef6a958 100644 --- a/app/services/todo_service.rb +++ b/app/services/todo_service.rb @@ -352,8 +352,6 @@ class TodoService end def reject_users_without_access(users, parent, target) - target = target.noteable if target.is_a?(Note) - if target.respond_to?(:to_ability_name) select_users(users, :"read_#{target.to_ability_name}", target) else diff --git a/debian/changelog b/debian/changelog index b52f9d5bf6..dfcc33b97f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,18 @@ +gitlab (14.8.6+ds1-1) experimental; urgency=medium + + * New upstream security release 14.8.6+ds1 (Fixes: CVE-2022-1423, + CVE-2022-1510, CVE-2022-1406, CVE-2022-1460, CVE-2022-1413, CVE-2022-1352, + CVE-2022-1428, CVE-2022-1417, CVE-2022-1124, CVE-2022-1416, CVE-2022-1431, + CVE-2022-1433, CVE-2022-1426) + + -- Pirate Praveen Tue, 03 May 2022 16:17:47 +0530 + +gitlab (14.8.5+ds1-4) experimental; urgency=medium + + * Update minimum version of js-cookie to 3.0 + + -- Pirate Praveen Mon, 02 May 2022 17:48:11 +0530 + gitlab (14.8.5+ds1-3~fto11+1) bullseye-fasttrack; urgency=medium * Rebuild for bullseye-fasttrack. diff --git a/debian/control b/debian/control index 3bb0f5cdaf..dcff252364 100644 --- a/debian/control +++ b/debian/control @@ -461,7 +461,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, node-jquery-ujs, # Broken # node-jquery.waitforimages, - node-js-cookie, + node-js-cookie (>= 3.0~), node-js-yaml (>= 3.13.1~), node-jszip, node-jszip-utils (>= 0.0.2+dfsg-2~), diff --git a/debian/patches/nodejs/0060-use-js-cookie-3.patch b/debian/patches/nodejs/0060-use-js-cookie-3.patch new file mode 100644 index 0000000000..cbe17c0fed --- /dev/null +++ b/debian/patches/nodejs/0060-use-js-cookie-3.patch @@ -0,0 +1,221 @@ +From 810896fdaccdba0e76e5062474420c6ce85493c3 Mon Sep 17 00:00:00 2001 +From: Pirate Praveen +Date: Wed, 20 Apr 2022 14:32:07 +0000 +Subject: [PATCH] Update node module js-cookies from ^2.2.1 to ^3.0.0 + +--- + app/assets/javascripts/lib/utils/common_utils.js | 2 +- + app/assets/javascripts/lib/utils/cookies.js | 8 ++++++++ + app/assets/javascripts/main.js | 4 ---- + .../javascripts/work_items_hierarchy/components/app.vue | 2 +- + .../components/qrtly_reconciliation_alert.vue | 2 +- + .../components/qrtly_reconciliation_alert_spec.js | 4 ++-- + ee/spec/frontend/ee_trial_banner/ee_trial_banner_spec.js | 2 +- + ee/spec/frontend/epic/utils/epic_utils_spec.js | 2 +- + ee/spec/frontend/namespace_storage_limit_alert_spec.js | 2 +- + ee/spec/frontend/namespace_user_cap_reached_alert_spec.js | 2 +- + .../project/project_vulnerability_report_spec.js | 2 +- + ee/spec/frontend/vulnerabilities/resolution_alert_spec.js | 2 +- + package.json | 2 +- + spec/frontend/awards_handler_spec.js | 2 +- + spec/frontend/blob/pipeline_tour_success_modal_spec.js | 2 +- + spec/frontend/broadcast_notification_spec.js | 2 +- + .../design_management/components/design_sidebar_spec.js | 2 +- + spec/frontend/diffs/store/actions_spec.js | 2 +- + spec/frontend/emoji/components/utils_spec.js | 4 ++-- + spec/frontend/groups/landing_spec.js | 2 +- + spec/frontend/merge_conflicts/store/actions_spec.js | 4 ++-- + .../projects/learn_gitlab/components/learn_gitlab_spec.js | 2 +- + .../shared/components/pipeline_schedule_callout_spec.js | 2 +- + .../sidebar/components/issuable_sidebar_root_spec.js | 2 +- + yarn.lock | 8 ++++---- + 25 files changed, 37 insertions(+), 33 deletions(-) + create mode 100644 app/assets/javascripts/lib/utils/cookies.js + +--- a/app/assets/javascripts/lib/utils/common_utils.js ++++ b/app/assets/javascripts/lib/utils/common_utils.js +@@ -4,8 +4,8 @@ + + import { GlBreakpointInstance as breakpointInstance } from '@gitlab/ui/dist/utils'; + import $ from 'jquery'; +-import Cookies from 'js-cookie'; + import { isFunction, defer } from 'lodash'; ++import Cookies from '~/lib/utils/cookies'; + import { SCOPED_LABEL_DELIMITER } from '~/vue_shared/components/sidebar/labels_select_widget/constants'; + import { convertToCamelCase, convertToSnakeCase } from './text_utility'; + import { isObject } from './type_utility'; +--- /dev/null ++++ b/app/assets/javascripts/lib/utils/cookies.js +@@ -0,0 +1,8 @@ ++import CookiesBuilder from 'js-cookie'; ++ ++// set default path for cookies ++const Cookies = CookiesBuilder.withAttributes({ ++ path: gon.relative_url_root || '/', ++}); ++ ++export default Cookies; +--- a/app/assets/javascripts/main.js ++++ b/app/assets/javascripts/main.js +@@ -1,7 +1,6 @@ + /* global $ */ + + import jQuery from 'jquery'; +-import Cookies from 'js-cookie'; + + // bootstrap webpack, common libs, polyfills, and behaviors + import './webpack'; +@@ -169,9 +168,6 @@ + initLayoutNav(); + initAlertHandler(); + +-// Set the default path for all cookies to GitLab's root directory +-Cookies.defaults.path = gon.relative_url_root || '/'; +- + // `hashchange` is not triggered when link target is already in window.location + $body.on('click', 'a[href^="#"]', function clickHashLinkCallback() { + const href = this.getAttribute('href'); +--- a/app/assets/javascripts/work_items_hierarchy/components/app.vue ++++ b/app/assets/javascripts/work_items_hierarchy/components/app.vue +@@ -1,6 +1,6 @@ +