mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Prevent possible XSS when using jQuery (#18289)
In the case of misuse or misunderstanding from a developer whereby, if `sel` can receive user-controlled data, jQuery `$(sel)` can lead to the creation of a new element. Current usage is using hard-coded selectors in the templates, but nobody prevents that from expanding to user-controlled somehow.
This commit is contained in:
		| @@ -127,3 +127,8 @@ We forbid `dataset` usage, its camel-casing behaviour makes it hard to grep for | |||||||
| ### Vue2/Vue3 and JSX | ### Vue2/Vue3 and JSX | ||||||
|  |  | ||||||
| Gitea is using Vue2 now, we plan to upgrade to Vue3. We decided not to introduce JSX to keep the HTML and the JavaScript code separated. | Gitea is using Vue2 now, we plan to upgrade to Vue3. We decided not to introduce JSX to keep the HTML and the JavaScript code separated. | ||||||
|  |  | ||||||
|  | ### jQuery's `$(...)` | ||||||
|  |  | ||||||
|  | jQuery's `$` function has a broad functionality depending on the input. Well, this can be seen as nice, it's also a fallpit for possible XSS attacks when the input is user-controlled. | ||||||
|  | The usage of the function can be correct in certain situations, but it is discourage and recommended to use a more specific function of jQuery(e.g. `$.find`, `$.parseHTML`). | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import Vue from 'vue'; | |||||||
| import {vueDelimiters} from './VueComponentLoader.js'; | import {vueDelimiters} from './VueComponentLoader.js'; | ||||||
|  |  | ||||||
| export function initRepoBranchTagDropdown(selector) { | export function initRepoBranchTagDropdown(selector) { | ||||||
|   $(selector).each(function () { |   $.find(selector).each(function () { | ||||||
|     const $dropdown = $(this); |     const $dropdown = $(this); | ||||||
|     const $data = $dropdown.find('.data'); |     const $data = $dropdown.find('.data'); | ||||||
|     const data = { |     const data = { | ||||||
|   | |||||||
| @@ -124,7 +124,7 @@ export function initGlobalCommon() { | |||||||
|   $('.tabable.menu .item').tab(); |   $('.tabable.menu .item').tab(); | ||||||
|  |  | ||||||
|   $('.toggle.button').on('click', function () { |   $('.toggle.button').on('click', function () { | ||||||
|     $($(this).data('target')).slideToggle(100); |     $.find($(this).data('target')).slideToggle(100); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   // make table <tr> and <td> elements clickable like a link |   // make table <tr> and <td> elements clickable like a link | ||||||
| @@ -202,7 +202,7 @@ export function initGlobalLinkActions() { | |||||||
|       closable: false, |       closable: false, | ||||||
|       onApprove() { |       onApprove() { | ||||||
|         if ($this.data('type') === 'form') { |         if ($this.data('type') === 'form') { | ||||||
|           $($this.data('form')).trigger('submit'); |           $.find($this.data('form')).trigger('submit'); | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -240,7 +240,7 @@ export function initGlobalLinkActions() { | |||||||
|       closable: false, |       closable: false, | ||||||
|       onApprove() { |       onApprove() { | ||||||
|         if ($this.data('type') === 'form') { |         if ($this.data('type') === 'form') { | ||||||
|           $($this.data('form')).trigger('submit'); |           $.find($this.data('form')).trigger('submit'); | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -293,7 +293,7 @@ export function initGlobalLinkActions() { | |||||||
|  |  | ||||||
| export function initGlobalButtons() { | export function initGlobalButtons() { | ||||||
|   $('.show-panel.button').on('click', function () { |   $('.show-panel.button').on('click', function () { | ||||||
|     $($(this).data('panel')).show(); |     $.find($(this).data('panel')).show(); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   $('.hide-panel.button').on('click', function (event) { |   $('.hide-panel.button').on('click', function (event) { | ||||||
| @@ -301,7 +301,7 @@ export function initGlobalButtons() { | |||||||
|     event.preventDefault(); |     event.preventDefault(); | ||||||
|     let sel = $(this).attr('data-panel'); |     let sel = $(this).attr('data-panel'); | ||||||
|     if (sel) { |     if (sel) { | ||||||
|       $(sel).hide(); |       $.find(sel).hide(); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     sel = $(this).attr('data-panel-closest'); |     sel = $(this).attr('data-panel-closest'); | ||||||
| @@ -314,8 +314,8 @@ export function initGlobalButtons() { | |||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   $('.show-modal.button').on('click', function () { |   $('.show-modal.button').on('click', function () { | ||||||
|     $($(this).data('modal')).modal('show'); |     $.find($(this).data('modal')).modal('show'); | ||||||
|     const colorPickers = $($(this).data('modal')).find('.color-picker'); |     const colorPickers = $.find($(this).data('modal')).find('.color-picker'); | ||||||
|     if (colorPickers.length > 0) { |     if (colorPickers.length > 0) { | ||||||
|       initCompColorPicker(); |       initCompColorPicker(); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import {initCompColorPicker} from './ColorPicker.js'; | import {initCompColorPicker} from './ColorPicker.js'; | ||||||
|  |  | ||||||
| export function initCompLabelEdit(selector) { | export function initCompLabelEdit(selector) { | ||||||
|   if (!$(selector).length) return; |   if (!$.find(selector).length) return; | ||||||
|   // Create label |   // Create label | ||||||
|   const $newLabelPanel = $('.new-label.segment'); |   const $newLabelPanel = $('.new-label.segment'); | ||||||
|   $('.new-label.button').on('click', () => { |   $('.new-label.button').on('click', () => { | ||||||
|   | |||||||
| @@ -2,6 +2,6 @@ export function initRepoBranchButton() { | |||||||
|   $('.show-create-branch-modal.button').on('click', function () { |   $('.show-create-branch-modal.button').on('click', function () { | ||||||
|     $('#create-branch-form')[0].action = $('#create-branch-form').data('base-action') + $(this).data('branch-from-urlcomponent'); |     $('#create-branch-form')[0].action = $('#create-branch-form').data('base-action') + $(this).data('branch-from-urlcomponent'); | ||||||
|     $('#modal-create-branch-from-span').text($(this).data('branch-from')); |     $('#modal-create-branch-from-span').text($(this).data('branch-from')); | ||||||
|     $($(this).data('modal')).modal('show'); |     $.find($(this).data('modal')).modal('show'); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -65,18 +65,18 @@ export function initRepoClone() { | |||||||
| } | } | ||||||
|  |  | ||||||
| export function initRepoCommonBranchOrTagDropdown(selector) { | export function initRepoCommonBranchOrTagDropdown(selector) { | ||||||
|   $(selector).each(function () { |   $.find(selector).each(function () { | ||||||
|     const $dropdown = $(this); |     const $dropdown = $(this); | ||||||
|     $dropdown.find('.reference.column').on('click', function () { |     $dropdown.find('.reference.column').on('click', function () { | ||||||
|       $dropdown.find('.scrolling.reference-list-menu').hide(); |       $dropdown.find('.scrolling.reference-list-menu').hide(); | ||||||
|       $($(this).data('target')).show(); |       $.find($(this).data('target')).show(); | ||||||
|       return false; |       return false; | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function initRepoCommonFilterSearchDropdown(selector) { | export function initRepoCommonFilterSearchDropdown(selector) { | ||||||
|   const $dropdown = $(selector); |   const $dropdown = $.find(selector); | ||||||
|   $dropdown.dropdown({ |   $dropdown.dropdown({ | ||||||
|     fullTextSearch: true, |     fullTextSearch: true, | ||||||
|     selectOnKeydown: false, |     selectOnKeydown: false, | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ export function initRepoDiffFileViewToggle() { | |||||||
|     $this.parent().children().removeClass('active'); |     $this.parent().children().removeClass('active'); | ||||||
|     $this.addClass('active'); |     $this.addClass('active'); | ||||||
|  |  | ||||||
|     const $target = $($this.data('toggle-selector')); |     const $target = $.find($this.data('toggle-selector')); | ||||||
|     $target.parent().children().addClass('hide'); |     $target.parent().children().addClass('hide'); | ||||||
|     $target.removeClass('hide'); |     $target.removeClass('hide'); | ||||||
|   }); |   }); | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ export function initRepoIssueTimeTracking() { | |||||||
|   }); |   }); | ||||||
|   $(document).on('click', 'button.issue-delete-time', function () { |   $(document).on('click', 'button.issue-delete-time', function () { | ||||||
|     const sel = `.issue-delete-time-modal[data-id="${$(this).data('id')}"]`; |     const sel = `.issue-delete-time-modal[data-id="${$(this).data('id')}"]`; | ||||||
|     $(sel).modal({ |     $.find(sel).modal({ | ||||||
|       duration: 200, |       duration: 200, | ||||||
|       onApprove() { |       onApprove() { | ||||||
|         $(`${sel} form`).trigger('submit'); |         $(`${sel} form`).trigger('submit'); | ||||||
| @@ -535,7 +535,7 @@ export function initRepoIssueReferenceIssue() { | |||||||
|     const content = $(`#comment-${$this.data('target')}`).text(); |     const content = $(`#comment-${$this.data('target')}`).text(); | ||||||
|     const poster = $this.data('poster-username'); |     const poster = $this.data('poster-username'); | ||||||
|     const reference = $this.data('reference'); |     const reference = $this.data('reference'); | ||||||
|     const $modal = $($this.data('modal')); |     const $modal = $.find($this.data('modal')); | ||||||
|     $modal.find('textarea[name="content"]').val(`${content}\n\n_Originally posted by @${poster} in ${reference}_`); |     $modal.find('textarea[name="content"]').val(`${content}\n\n_Originally posted by @${poster} in ${reference}_`); | ||||||
|     $modal.modal('show'); |     $modal.modal('show'); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ export function initRepoCommentForm() { | |||||||
|     $branchMenu.find('.item:not(.no-select)').click(function () { |     $branchMenu.find('.item:not(.no-select)').click(function () { | ||||||
|       const selectedValue = $(this).data('id'); |       const selectedValue = $(this).data('id'); | ||||||
|       const editMode = $('#editing_mode').val(); |       const editMode = $('#editing_mode').val(); | ||||||
|       $($(this).data('id-selector')).val(selectedValue); |       $.find($(this).data('id-selector')).val(selectedValue); | ||||||
|       if ($isNewIssue) { |       if ($isNewIssue) { | ||||||
|         $selectBranch.find('.ui .branch-name').text($(this).data('name')); |         $selectBranch.find('.ui .branch-name').text($(this).data('name')); | ||||||
|         return; |         return; | ||||||
| @@ -58,7 +58,7 @@ export function initRepoCommentForm() { | |||||||
|     $selectBranch.find('.reference.column').on('click', function () { |     $selectBranch.find('.reference.column').on('click', function () { | ||||||
|       $selectBranch.find('.scrolling.reference-list-menu').css('display', 'none'); |       $selectBranch.find('.scrolling.reference-list-menu').css('display', 'none'); | ||||||
|       $selectBranch.find('.reference .text').removeClass('black'); |       $selectBranch.find('.reference .text').removeClass('black'); | ||||||
|       $($(this).data('target')).css('display', 'block'); |       $.find($(this).data('target')).css('display', 'block'); | ||||||
|       $(this).find('.text').addClass('black'); |       $(this).find('.text').addClass('black'); | ||||||
|       return false; |       return false; | ||||||
|     }); |     }); | ||||||
| @@ -145,9 +145,9 @@ export function initRepoCommentForm() { | |||||||
|       $(this).parent().find('.item').each(function () { |       $(this).parent().find('.item').each(function () { | ||||||
|         if ($(this).hasClass('checked')) { |         if ($(this).hasClass('checked')) { | ||||||
|           listIds.push($(this).data('id')); |           listIds.push($(this).data('id')); | ||||||
|           $($(this).data('id-selector')).removeClass('hide'); |           $.find($(this).data('id-selector')).removeClass('hide'); | ||||||
|         } else { |         } else { | ||||||
|           $($(this).data('id-selector')).addClass('hide'); |           $.find($(this).data('id-selector')).addClass('hide'); | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|       if (listIds.length === 0) { |       if (listIds.length === 0) { | ||||||
| @@ -155,7 +155,7 @@ export function initRepoCommentForm() { | |||||||
|       } else { |       } else { | ||||||
|         $noSelect.addClass('hide'); |         $noSelect.addClass('hide'); | ||||||
|       } |       } | ||||||
|       $($(this).parent().data('id')).val(listIds.join(',')); |       $.find($(this).parent().data('id')).val(listIds.join(',')); | ||||||
|       return false; |       return false; | ||||||
|     }); |     }); | ||||||
|     $listMenu.find('.no-select.item').on('click', function (e) { |     $listMenu.find('.no-select.item').on('click', function (e) { | ||||||
| @@ -182,7 +182,7 @@ export function initRepoCommentForm() { | |||||||
|         $(this).addClass('hide'); |         $(this).addClass('hide'); | ||||||
|       }); |       }); | ||||||
|       $noSelect.removeClass('hide'); |       $noSelect.removeClass('hide'); | ||||||
|       $($(this).parent().data('id')).val(''); |       $.find($(this).parent().data('id')).val(''); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -247,7 +247,7 @@ export function initRepoCommentForm() { | |||||||
|  |  | ||||||
|       $list.find('.selected').html(''); |       $list.find('.selected').html(''); | ||||||
|       $list.find('.no-select').removeClass('hide'); |       $list.find('.no-select').removeClass('hide'); | ||||||
|       $(input_id).val(''); |       $.find(input_id).val(''); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -450,20 +450,20 @@ export function initRepository() { | |||||||
|     // Enable or select internal/external wiki system and issue tracker. |     // Enable or select internal/external wiki system and issue tracker. | ||||||
|     $('.enable-system').on('change', function () { |     $('.enable-system').on('change', function () { | ||||||
|       if (this.checked) { |       if (this.checked) { | ||||||
|         $($(this).data('target')).removeClass('disabled'); |         $.find($(this).data('target')).removeClass('disabled'); | ||||||
|         if (!$(this).data('context')) $($(this).data('context')).addClass('disabled'); |         if (!$(this).data('context')) $.find($(this).data('context')).addClass('disabled'); | ||||||
|       } else { |       } else { | ||||||
|         $($(this).data('target')).addClass('disabled'); |         $.find($(this).data('target')).addClass('disabled'); | ||||||
|         if (!$(this).data('context')) $($(this).data('context')).removeClass('disabled'); |         if (!$(this).data('context')) $.find($(this).data('context')).removeClass('disabled'); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|     $('.enable-system-radio').on('change', function () { |     $('.enable-system-radio').on('change', function () { | ||||||
|       if (this.value === 'false') { |       if (this.value === 'false') { | ||||||
|         $($(this).data('target')).addClass('disabled'); |         $.find($(this).data('target')).addClass('disabled'); | ||||||
|         if (typeof $(this).data('context') !== 'undefined') $($(this).data('context')).removeClass('disabled'); |         if (typeof $(this).data('context') !== 'undefined') $.find($(this).data('context')).removeClass('disabled'); | ||||||
|       } else if (this.value === 'true') { |       } else if (this.value === 'true') { | ||||||
|         $($(this).data('target')).removeClass('disabled'); |         $.find($(this).data('target')).removeClass('disabled'); | ||||||
|         if (typeof $(this).data('context') !== 'undefined') $($(this).data('context')).addClass('disabled'); |         if (typeof $(this).data('context') !== 'undefined') $.find($(this).data('context')).addClass('disabled'); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -52,14 +52,14 @@ export function initRepoSettingBranches() { | |||||||
|     initRepoCommonFilterSearchDropdown('.protected-branches .dropdown'); |     initRepoCommonFilterSearchDropdown('.protected-branches .dropdown'); | ||||||
|     $('.enable-protection, .enable-whitelist, .enable-statuscheck').on('change', function () { |     $('.enable-protection, .enable-whitelist, .enable-statuscheck').on('change', function () { | ||||||
|       if (this.checked) { |       if (this.checked) { | ||||||
|         $($(this).data('target')).removeClass('disabled'); |         $.find($(this).data('target')).removeClass('disabled'); | ||||||
|       } else { |       } else { | ||||||
|         $($(this).data('target')).addClass('disabled'); |         $.find($(this).data('target')).addClass('disabled'); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|     $('.disable-whitelist').on('change', function () { |     $('.disable-whitelist').on('change', function () { | ||||||
|       if (this.checked) { |       if (this.checked) { | ||||||
|         $($(this).data('target')).addClass('disabled'); |         $.find($(this).data('target')).addClass('disabled'); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Gusted
					Gusted