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.
tokarchuk/v1.17
Gusted 3 years ago committed by GitHub
parent 4b4884ce88
commit 661d3d28e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      docs/content/doc/developers/guidelines-frontend.md
  2. 2
      web_src/js/components/RepoBranchTagDropdown.js
  3. 14
      web_src/js/features/common-global.js
  4. 2
      web_src/js/features/comp/LabelEdit.js
  5. 2
      web_src/js/features/repo-branch.js
  6. 6
      web_src/js/features/repo-common.js
  7. 2
      web_src/js/features/repo-diff.js
  8. 4
      web_src/js/features/repo-issue.js
  9. 30
      web_src/js/features/repo-legacy.js
  10. 6
      web_src/js/features/repo-settings.js

@ -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');
} }
}); });
} }

Loading…
Cancel
Save