diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 486da5bb90..882ae337c6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -130,27 +130,6 @@ variables: REGISTRY_HOST: "registry.gitlab.com" REGISTRY_GROUP: "gitlab-org" - # Preparing custom clone path to reduce space used by all random forks - # on GitLab.com's Shared Runners. Our main forks - especially the security - # ones - will have this variable overwritten in the project settings, so that - # a security-related code or code using our protected variables will be never - # stored on the same path as the community forks. - # Part of the solution for the `no space left on device` problem described at - # https://gitlab.com/gitlab-org/gitlab/issues/197876. - # - # For this purpose the https://gitlab.com/gitlab-org-forks group was created - # to host a placeholder for the `/builds/gitlab-org-forks` path and ensure - # that no legitimate project will ever use it and - by mistake - execute its - # job on a shared working directory. It also requires proper configuration of - # the Runner that executes the job (which was prepared for our shared runners - # by https://ops.gitlab.net/gitlab-cookbooks/chef-repo/-/merge_requests/3977). - # - # Because of all of that PLEASE DO NOT CHANGE THE PATH. - # - # For more details and reasoning that brought this change please check - # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24887 - GIT_CLONE_PATH: "/builds/gitlab-org-forks/${CI_PROJECT_NAME}" - include: - local: .gitlab/ci/*.gitlab-ci.yml - remote: 'https://gitlab.com/gitlab-org/frontend/untamper-my-lockfile/-/raw/main/templates/merge_request_pipelines.yml' diff --git a/.rubocop_todo/style/string_concatenation.yml b/.rubocop_todo/style/string_concatenation.yml index 2330683cc1..32ea84fbfc 100644 --- a/.rubocop_todo/style/string_concatenation.yml +++ b/.rubocop_todo/style/string_concatenation.yml @@ -263,6 +263,7 @@ Style/StringConcatenation: - 'spec/models/custom_emoji_spec.rb' - 'spec/models/grafana_integration_spec.rb' - 'spec/models/integrations/campfire_spec.rb' + - 'spec/models/integrations/datadog_spec.rb' - 'spec/models/integrations/chat_message/pipeline_message_spec.rb' - 'spec/models/integrations/chat_message/push_message_spec.rb' - 'spec/models/integrations/jenkins_spec.rb' diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b2d11964..0d59a3e7e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,36 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 15.3.4 (2022-09-29) + +### Security (15 changes) + +- [Redact user's private email in group member event webhook](gitlab-org/security/gitlab@172b8a57bd4acca14d65a4b7a5fd021babacb146) ([merge request](gitlab-org/security/gitlab!2794)) +- [Redact secrets from WebHookLogs](gitlab-org/security/gitlab@7394ab9b32a7bd83b98f93e904312e469f34cd9c) ([merge request](gitlab-org/security/gitlab!2737)) +- [Forbid creating a tag using default branch name](gitlab-org/security/gitlab@1b556c33aa11c32994be562cfea0ff2e5e13a54e) ([merge request](gitlab-org/security/gitlab!2799)) +- [Sanitize Url and check for valid numerical errorId in error tracking](gitlab-org/security/gitlab@2a5a51b5b2839963fe7084261c8a7fcc6f09f19c) ([merge request](gitlab-org/security/gitlab!2785)) +- [Add security protection for Github](gitlab-org/security/gitlab@bc23f46dba26bcdf0c773c24081e4ae3597bf751) ([merge request](gitlab-org/security/gitlab!2802)) +- [Fix leaking emails in WebHookLogs](gitlab-org/security/gitlab@a31a652c331877e0f97269310ec5f1bc6266398f) ([merge request](gitlab-org/security/gitlab!2807)) +- [Restrict max duration to 1 year for trace display](gitlab-org/security/gitlab@b62fd774b6f311988c7e10f3544f2aeabeab85d1) ([merge request](gitlab-org/security/gitlab!2815)) +- [Use UntrustedRegexp for upload rewriter](gitlab-org/security/gitlab@2eea36acbc5687aa9806946861e73f2fb11a9654) ([merge request](gitlab-org/security/gitlab!2791)) +- [Validate httpUrlToRepo to be http or https only](gitlab-org/security/gitlab@0b340ef6d6e54804445916f5b1fa53185de4b1f7) ([merge request](gitlab-org/security/gitlab!2760)) +- [Respect instance level rule for editing approval rules](gitlab-org/security/gitlab@2d2a7b8652dbd1085fe1bfc0b69138aecdeaf9c8) ([merge request](gitlab-org/security/gitlab!2782)) +- [Prevent users creating issues in ay project via board/issues controller](gitlab-org/security/gitlab@559b23e6942a650cafa358ea96b7ee549f76fbd6) ([merge request](gitlab-org/security/gitlab!2780)) +- [Prevent serialization of sensible attributes from JsonCache](gitlab-org/security/gitlab@f712d58af3aeb3f0fe1c56a290188e19fce72ad6) ([merge request](gitlab-org/security/gitlab!2771)) +- [Update TodoPolicy to handle confidential notes](gitlab-org/security/gitlab@6bd37cd0595bbf4c744a5b212fc41181c9dc88ef) ([merge request](gitlab-org/security/gitlab!2748)) +- [Enforce group IP restriction on Dependency Proxy](gitlab-org/security/gitlab@cc42b5e91e04e77ade63f1fdb91e88b998c156f7) ([merge request](gitlab-org/security/gitlab!2764)) +- [Fixes XSS in widget extensions](gitlab-org/security/gitlab@1d10849c7eee6207435bfd223e1f8639b2816c1e) ([merge request](gitlab-org/security/gitlab!2759)) + +## 15.3.3 (2022-09-01) + +### Fixed (5 changes) + +- [Skip file removal if GitLab managed replication is disabled](gitlab-org/gitlab@dbec61270621df70775c98946d09deca913bd187) ([merge request](gitlab-org/gitlab!96556)) **GitLab Enterprise Edition** +- [Geo: Fix redirects of LFS transfer downloads](gitlab-org/gitlab@98092958c879d1dc9dda0ba2953ba548aa0b93c0) ([merge request](gitlab-org/gitlab!96654)) **GitLab Enterprise Edition** +- [Improve blame link feature](gitlab-org/gitlab@163cadb49f96951a0f747d61a8cd1cb92b7d4296) ([merge request](gitlab-org/gitlab!96654)) +- [Bypass earliest date validation in importing of iteration cadences](gitlab-org/gitlab@66f56eb2551a302d80ca0891ff0bddec1c84f025) ([merge request](gitlab-org/gitlab!96654)) **GitLab Enterprise Edition** +- [Fix user recent activity links for work item actions](gitlab-org/gitlab@9d9368545847cf558fad26a64b216a00b2db36b4) ([merge request](gitlab-org/gitlab!96654)) + ## 15.3.2 (2022-08-30) ### Security (17 changes) diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 7bb26bde92..3cad8b789c 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -15.3.2 \ No newline at end of file +15.3.4 \ No newline at end of file diff --git a/VERSION b/VERSION index 7bb26bde92..3cad8b789c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -15.3.2 \ No newline at end of file +15.3.4 \ No newline at end of file diff --git a/app/assets/javascripts/batch_comments/components/review_bar.vue b/app/assets/javascripts/batch_comments/components/review_bar.vue index 111b670596..3cd1a2525e 100644 --- a/app/assets/javascripts/batch_comments/components/review_bar.vue +++ b/app/assets/javascripts/batch_comments/components/review_bar.vue @@ -2,20 +2,10 @@ import { mapActions, mapGetters } from 'vuex'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { REVIEW_BAR_VISIBLE_CLASS_NAME } from '../constants'; -import { PREVENT_LEAVING_PENDING_REVIEW } from '../i18n'; import PreviewDropdown from './preview_dropdown.vue'; import PublishButton from './publish_button.vue'; import SubmitDropdown from './submit_dropdown.vue'; -function closeInterrupt(event) { - event.preventDefault(); - - // This is the correct way to write backwards-compatible beforeunload listeners - // https://developer.chrome.com/blog/page-lifecycle-api/#the-beforeunload-event - /* eslint-disable-next-line no-return-assign, no-param-reassign */ - return (event.returnValue = PREVENT_LEAVING_PENDING_REVIEW); -} - export default { components: { PreviewDropdown, @@ -35,26 +25,8 @@ export default { }, mounted() { document.body.classList.add(REVIEW_BAR_VISIBLE_CLASS_NAME); - /* - * This stuff is a lot trickier than it looks. - * - * Mandatory reading: https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event - * Some notable sentences: - * - "[...] browsers may not display prompts created in beforeunload event handlers unless the - * page has been interacted with, or may even not display them at all." - * - "Especially on mobile, the beforeunload event is not reliably fired." - * - "The beforeunload event is not compatible with the back/forward cache (bfcache) [...] - * It is recommended that developers listen for beforeunload only in this scenario, and only - * when they actually have unsaved changes, so as to minimize the effect on performance." - * - * Please ensure that this is really not working before you modify it, because there are a LOT - * of scenarios where browser behavior will make it _seem_ like it's not working, but it actually - * is under the right combination of contexts. - */ - window.addEventListener('beforeunload', closeInterrupt, { capture: true }); }, beforeDestroy() { - window.removeEventListener('beforeunload', closeInterrupt, { capture: true }); document.body.classList.remove(REVIEW_BAR_VISIBLE_CLASS_NAME); }, methods: { diff --git a/app/assets/javascripts/batch_comments/i18n.js b/app/assets/javascripts/batch_comments/i18n.js deleted file mode 100644 index 6cdbf00f9c..0000000000 --- a/app/assets/javascripts/batch_comments/i18n.js +++ /dev/null @@ -1,3 +0,0 @@ -import { __ } from '~/locale'; - -export const PREVENT_LEAVING_PENDING_REVIEW = __('There are unsubmitted review comments.'); diff --git a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js index 863d2a9997..a44b9827fe 100644 --- a/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js +++ b/app/assets/javascripts/batch_comments/stores/modules/batch_comments/actions.js @@ -1,12 +1,9 @@ import { isEmpty } from 'lodash'; - import createFlash from '~/flash'; import { scrollToElement } from '~/lib/utils/common_utils'; import { __ } from '~/locale'; - import { CHANGES_TAB, DISCUSSION_TAB, SHOW_TAB } from '../../../constants'; import service from '../../../services/drafts_service'; - import * as types from './mutation_types'; export const saveDraft = ({ dispatch }, draft) => @@ -18,7 +15,6 @@ export const addDraftToDiscussion = ({ commit }, { endpoint, data }) => .then((res) => res.data) .then((res) => { commit(types.ADD_NEW_DRAFT, res); - return res; }) .catch(() => { @@ -33,7 +29,6 @@ export const createNewDraft = ({ commit }, { endpoint, data }) => .then((res) => res.data) .then((res) => { commit(types.ADD_NEW_DRAFT, res); - return res; }) .catch(() => { diff --git a/app/assets/javascripts/blob/blob_blame_link.js b/app/assets/javascripts/blob/blob_blame_link.js new file mode 100644 index 0000000000..41dfd7b82b --- /dev/null +++ b/app/assets/javascripts/blob/blob_blame_link.js @@ -0,0 +1,31 @@ +function addBlameLink(containerSelector, linkClass) { + const containerEl = document.querySelector(containerSelector); + + if (!containerEl) { + return; + } + + containerEl.addEventListener('mouseover', (e) => { + const isLineLink = e.target.classList.contains(linkClass); + if (isLineLink) { + const lineLink = e.target; + const lineLinkCopy = lineLink.cloneNode(true); + lineLinkCopy.classList.remove(linkClass, 'diff-line-num'); + + const { lineNumber } = lineLink.dataset; + const { blamePath } = document.querySelector('.line-numbers').dataset; + const blameLink = document.createElement('a'); + blameLink.classList.add('file-line-blame'); + blameLink.href = `${blamePath}#L${lineNumber}`; + + const wrapper = document.createElement('div'); + wrapper.classList.add('line-links', 'diff-line-num'); + + wrapper.appendChild(blameLink); + wrapper.appendChild(lineLinkCopy); + lineLink.replaceWith(wrapper); + } + }); +} + +export default addBlameLink; diff --git a/app/assets/javascripts/blob/blob_links_tracking.js b/app/assets/javascripts/blob/blob_links_tracking.js index 9a49aa8b0f..713cc3fad0 100644 --- a/app/assets/javascripts/blob/blob_links_tracking.js +++ b/app/assets/javascripts/blob/blob_links_tracking.js @@ -1,7 +1,12 @@ import Tracking from '~/tracking'; -function addBlobLinksTracking(containerSelector, eventsToTrack) { - const containerEl = document.querySelector(containerSelector); +const eventsToTrack = [ + { selector: '.file-line-blame', property: 'blame' }, + { selector: '.file-line-num', property: 'link' }, +]; + +function addBlobLinksTracking() { + const containerEl = document.querySelector('.file-holder'); if (!containerEl) { return; diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue index a07428dafe..de4b11699f 100644 --- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue +++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue @@ -22,12 +22,16 @@ import AccessorUtils from '~/lib/utils/accessor'; import { __ } from '~/locale'; import Tracking from '~/tracking'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; +import { sanitizeUrl } from '~/lib/utils/url_utility'; import { trackErrorListViewsOptions, trackErrorStatusUpdateOptions } from '../utils'; import { I18N_ERROR_TRACKING_LIST } from '../constants'; import ErrorTrackingActions from './error_tracking_actions.vue'; export const tableDataClass = 'table-col d-flex d-md-table-cell align-items-center'; +const isValidErrorId = (errorId) => { + return /^[0-9]+$/.test(errorId); +}; export default { FIRST_PAGE: 1, PREV_PAGE: 1, @@ -202,6 +206,9 @@ export default { this.searchByQuery(text); }, getDetailsLink(errorId) { + if (!isValidErrorId(errorId)) { + return 'about:blank'; + } return `error_tracking/${errorId}/details`; }, goToNextPage() { @@ -222,7 +229,10 @@ export default { return filter === this.statusFilter; }, getIssueUpdatePath(errorId) { - return `/${this.projectPath}/-/error_tracking/${errorId}.json`; + if (!isValidErrorId(errorId)) { + return 'about:blank'; + } + return sanitizeUrl(`/${this.projectPath}/-/error_tracking/${errorId}.json`); }, filterErrors(status, label) { this.filterValue = label; diff --git a/app/assets/javascripts/pages/projects/init_blob.js b/app/assets/javascripts/pages/projects/init_blob.js index f7849e8d58..f37a298768 100644 --- a/app/assets/javascripts/pages/projects/init_blob.js +++ b/app/assets/javascripts/pages/projects/init_blob.js @@ -4,7 +4,6 @@ import BlobForkSuggestion from '~/blob/blob_fork_suggestion'; import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater'; import LineHighlighter from '~/blob/line_highlighter'; import initBlobBundle from '~/blob_edit/blob_bundle'; -import addBlobLinksTracking from '~/blob/blob_links_tracking'; export default () => { new LineHighlighter(); // eslint-disable-line no-new @@ -16,12 +15,6 @@ export default () => { document.querySelectorAll('.js-data-file-blob-permalink-url, .js-blob-blame-link'), ); - const eventsToTrack = [ - { selector: '.file-line-blame', property: 'blame' }, - { selector: '.file-line-num', property: 'link' }, - ]; - addBlobLinksTracking('#blob-content-holder', eventsToTrack); - const fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url'); const fileBlobPermalinkUrl = fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href'); diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue index 7999b916e0..78572f11f6 100644 --- a/app/assets/javascripts/repository/components/blob_content_viewer.vue +++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue @@ -13,6 +13,7 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import WebIdeLink from '~/vue_shared/components/web_ide_link.vue'; import CodeIntelligence from '~/code_navigation/components/app.vue'; import LineHighlighter from '~/blob/line_highlighter'; +import addBlameLink from '~/blob/blob_blame_link'; import getRefMixin from '../mixins/get_ref'; import blobInfoQuery from '../queries/blob_info.query.graphql'; import userInfoQuery from '../queries/user_info.query.graphql'; @@ -242,6 +243,7 @@ export default { if (type === SIMPLE_BLOB_VIEWER) { new LineHighlighter(); // eslint-disable-line no-new + addBlameLink('.file-holder', 'js-line-links'); } }); diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue index 1eccc7de66..99576a8dd9 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue @@ -1,5 +1,6 @@ - -CODE - -git commit: "-a -m 'Added loading Bootstrap assets in the application layout'" - -# ----- Customize the search form ----------------------------------------------------------------- - -puts -say_status "Bootstrap", "Customizing the index page...\n", :yellow -puts '-'*80, ''; sleep 0.5 - -gsub_file 'app/views/articles/index.html.erb', %r{<%= label_tag .* :search %>}m do |match| -<<-CODE -
- <%= text_field_tag :q, params[:q], class: 'form-control', placeholder: 'Search...' %> -
-CODE -end - -# ----- Customize the header ----------------------------------------------------------------- - -gsub_file 'app/views/articles/index.html.erb', %r{

.*Articles

} do |match| - "

<%= controller.action_name == 'search' ? 'Search results' : 'Articles' %>

" -end - -# ----- Customize the results listing ------------------------------------------------------------- - -gsub_file 'app/views/articles/index.html.erb', %r{} do |match| - '
' -end - -gsub_file 'app/views/articles/index.html.erb', %r{$} do |match| - "" -end - -gsub_file 'app/views/articles/index.html.erb', %r{$} do |match| - "" -end - -git commit: "-a -m 'Added highlighting for matches'" - -# ----- Paginate the results ---------------------------------------------------------------------- - -gsub_file 'app/controllers/articles_controller.rb', %r{@articles = Article.all} do |match| - "@articles = Article.page(params[:page])" -end - -gsub_file 'app/controllers/articles_controller.rb', %r{@articles = Article.search\(params\[\:q\]\).records} do |match| - "@articles = Article.search(params[:q]).page(params[:page]).records" -end - -insert_into_file 'app/views/articles/index.html.erb', after: '
<%= link_to [^%]+} do |match| - match.gsub!('', '') - match.include?("btn") ? match : (match + ", class: 'btn btn-outline-primary btn-sm'") -end - -gsub_file 'app/views/articles/index.html.erb', %r{
\s*(<\%= link_to 'New Article'.*)}m do |content| - replace = content.match(%r{
\s*(<\%= link_to 'New Article'.*)}m)[1] - <<-END.gsub(/^ /, '') -
- -

- #{replace} -

- END -end - -gsub_file 'app/views/articles/index.html.erb', %r{<%= link_to 'New Article',\s*new_article_path} do |match| - return match if match.include?('btn') - match + ", class: 'btn btn-primary btn-xs', style: 'color: #fff'" -end - -gsub_file 'app/views/articles/index.html.erb', %r{<%= link_to 'All Articles',\s*articles_path} do |match| - return match if match.include?('btn') - "\n " + match + ", class: 'btn btn-primary btn-xs', style: 'color: #fff'" -end - -# ----- Customize the form ----------------------------------------------------------------- - -gsub_file 'app/views/articles/_form.html.erb', %r{
} do |match| - %Q|
| -end - -git add: "app/views" -git commit: "-m 'Refactored the articles listing to use Bootstrap components'" - -# ----- Use highlighted excerpts in the listing --------------------------------------------------- - -gsub_file 'app/views/articles/index.html.erb', %r{<% @articles.each do \|article\| %>$} do |match| - "<% @articles.__send__ controller.action_name == 'search' ? :each_with_hit : :each do |article, hit| %>" -end - -gsub_file 'app/views/articles/index.html.erb', %r{
<%= article.title %><%= hit.try(:highlight).try(:title) ? hit.highlight.title.join.html_safe : article.title %><%= article.content %><%= hit.try(:highlight).try(:content) ? hit.highlight.content.join('…').html_safe : article.content %>
' do - <<-CODE.gsub(/^ /, '') - - -
- <%= paginate @articles %> -
- CODE -end - -generate "kaminari:views", "bootstrap3", "--force" - -gsub_file 'app/views/kaminari/_paginator.html.erb', %r{