Skip to content

Commit 661d3d2

Browse files
author
Gusted
authored
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.
1 parent 4b4884c commit 661d3d2

File tree

10 files changed

+39
-34
lines changed

10 files changed

+39
-34
lines changed

docs/content/doc/developers/guidelines-frontend.md

+5
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,8 @@ We forbid `dataset` usage, its camel-casing behaviour makes it hard to grep for
127127
### Vue2/Vue3 and JSX
128128

129129
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.
130+
131+
### jQuery's `$(...)`
132+
133+
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.
134+
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`).

web_src/js/components/RepoBranchTagDropdown.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Vue from 'vue';
22
import {vueDelimiters} from './VueComponentLoader.js';
33

44
export function initRepoBranchTagDropdown(selector) {
5-
$(selector).each(function () {
5+
$.find(selector).each(function () {
66
const $dropdown = $(this);
77
const $data = $dropdown.find('.data');
88
const data = {

web_src/js/features/common-global.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export function initGlobalCommon() {
124124
$('.tabable.menu .item').tab();
125125

126126
$('.toggle.button').on('click', function () {
127-
$($(this).data('target')).slideToggle(100);
127+
$.find($(this).data('target')).slideToggle(100);
128128
});
129129

130130
// make table <tr> and <td> elements clickable like a link
@@ -202,7 +202,7 @@ export function initGlobalLinkActions() {
202202
closable: false,
203203
onApprove() {
204204
if ($this.data('type') === 'form') {
205-
$($this.data('form')).trigger('submit');
205+
$.find($this.data('form')).trigger('submit');
206206
return;
207207
}
208208

@@ -240,7 +240,7 @@ export function initGlobalLinkActions() {
240240
closable: false,
241241
onApprove() {
242242
if ($this.data('type') === 'form') {
243-
$($this.data('form')).trigger('submit');
243+
$.find($this.data('form')).trigger('submit');
244244
return;
245245
}
246246

@@ -293,15 +293,15 @@ export function initGlobalLinkActions() {
293293

294294
export function initGlobalButtons() {
295295
$('.show-panel.button').on('click', function () {
296-
$($(this).data('panel')).show();
296+
$.find($(this).data('panel')).show();
297297
});
298298

299299
$('.hide-panel.button').on('click', function (event) {
300300
// a `.hide-panel.button` can hide a panel, by `data-panel="selector"` or `data-panel-closest="selector"`
301301
event.preventDefault();
302302
let sel = $(this).attr('data-panel');
303303
if (sel) {
304-
$(sel).hide();
304+
$.find(sel).hide();
305305
return;
306306
}
307307
sel = $(this).attr('data-panel-closest');
@@ -314,8 +314,8 @@ export function initGlobalButtons() {
314314
});
315315

316316
$('.show-modal.button').on('click', function () {
317-
$($(this).data('modal')).modal('show');
318-
const colorPickers = $($(this).data('modal')).find('.color-picker');
317+
$.find($(this).data('modal')).modal('show');
318+
const colorPickers = $.find($(this).data('modal')).find('.color-picker');
319319
if (colorPickers.length > 0) {
320320
initCompColorPicker();
321321
}

web_src/js/features/comp/LabelEdit.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {initCompColorPicker} from './ColorPicker.js';
22

33
export function initCompLabelEdit(selector) {
4-
if (!$(selector).length) return;
4+
if (!$.find(selector).length) return;
55
// Create label
66
const $newLabelPanel = $('.new-label.segment');
77
$('.new-label.button').on('click', () => {

web_src/js/features/repo-branch.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ export function initRepoBranchButton() {
22
$('.show-create-branch-modal.button').on('click', function () {
33
$('#create-branch-form')[0].action = $('#create-branch-form').data('base-action') + $(this).data('branch-from-urlcomponent');
44
$('#modal-create-branch-from-span').text($(this).data('branch-from'));
5-
$($(this).data('modal')).modal('show');
5+
$.find($(this).data('modal')).modal('show');
66
});
77
}

web_src/js/features/repo-common.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,18 @@ export function initRepoClone() {
6565
}
6666

6767
export function initRepoCommonBranchOrTagDropdown(selector) {
68-
$(selector).each(function () {
68+
$.find(selector).each(function () {
6969
const $dropdown = $(this);
7070
$dropdown.find('.reference.column').on('click', function () {
7171
$dropdown.find('.scrolling.reference-list-menu').hide();
72-
$($(this).data('target')).show();
72+
$.find($(this).data('target')).show();
7373
return false;
7474
});
7575
});
7676
}
7777

7878
export function initRepoCommonFilterSearchDropdown(selector) {
79-
const $dropdown = $(selector);
79+
const $dropdown = $.find(selector);
8080
$dropdown.dropdown({
8181
fullTextSearch: true,
8282
selectOnKeydown: false,

web_src/js/features/repo-diff.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function initRepoDiffFileViewToggle() {
1515
$this.parent().children().removeClass('active');
1616
$this.addClass('active');
1717

18-
const $target = $($this.data('toggle-selector'));
18+
const $target = $.find($this.data('toggle-selector'));
1919
$target.parent().children().addClass('hide');
2020
$target.removeClass('hide');
2121
});

web_src/js/features/repo-issue.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function initRepoIssueTimeTracking() {
2828
});
2929
$(document).on('click', 'button.issue-delete-time', function () {
3030
const sel = `.issue-delete-time-modal[data-id="${$(this).data('id')}"]`;
31-
$(sel).modal({
31+
$.find(sel).modal({
3232
duration: 200,
3333
onApprove() {
3434
$(`${sel} form`).trigger('submit');
@@ -535,7 +535,7 @@ export function initRepoIssueReferenceIssue() {
535535
const content = $(`#comment-${$this.data('target')}`).text();
536536
const poster = $this.data('poster-username');
537537
const reference = $this.data('reference');
538-
const $modal = $($this.data('modal'));
538+
const $modal = $.find($this.data('modal'));
539539
$modal.find('textarea[name="content"]').val(`${content}\n\n_Originally posted by @${poster} in ${reference}_`);
540540
$modal.modal('show');
541541

web_src/js/features/repo-legacy.js

+15-15
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export function initRepoCommentForm() {
4242
$branchMenu.find('.item:not(.no-select)').click(function () {
4343
const selectedValue = $(this).data('id');
4444
const editMode = $('#editing_mode').val();
45-
$($(this).data('id-selector')).val(selectedValue);
45+
$.find($(this).data('id-selector')).val(selectedValue);
4646
if ($isNewIssue) {
4747
$selectBranch.find('.ui .branch-name').text($(this).data('name'));
4848
return;
@@ -58,7 +58,7 @@ export function initRepoCommentForm() {
5858
$selectBranch.find('.reference.column').on('click', function () {
5959
$selectBranch.find('.scrolling.reference-list-menu').css('display', 'none');
6060
$selectBranch.find('.reference .text').removeClass('black');
61-
$($(this).data('target')).css('display', 'block');
61+
$.find($(this).data('target')).css('display', 'block');
6262
$(this).find('.text').addClass('black');
6363
return false;
6464
});
@@ -145,17 +145,17 @@ export function initRepoCommentForm() {
145145
$(this).parent().find('.item').each(function () {
146146
if ($(this).hasClass('checked')) {
147147
listIds.push($(this).data('id'));
148-
$($(this).data('id-selector')).removeClass('hide');
148+
$.find($(this).data('id-selector')).removeClass('hide');
149149
} else {
150-
$($(this).data('id-selector')).addClass('hide');
150+
$.find($(this).data('id-selector')).addClass('hide');
151151
}
152152
});
153153
if (listIds.length === 0) {
154154
$noSelect.removeClass('hide');
155155
} else {
156156
$noSelect.addClass('hide');
157157
}
158-
$($(this).parent().data('id')).val(listIds.join(','));
158+
$.find($(this).parent().data('id')).val(listIds.join(','));
159159
return false;
160160
});
161161
$listMenu.find('.no-select.item').on('click', function (e) {
@@ -182,7 +182,7 @@ export function initRepoCommentForm() {
182182
$(this).addClass('hide');
183183
});
184184
$noSelect.removeClass('hide');
185-
$($(this).parent().data('id')).val('');
185+
$.find($(this).parent().data('id')).val('');
186186
});
187187
}
188188

@@ -247,7 +247,7 @@ export function initRepoCommentForm() {
247247

248248
$list.find('.selected').html('');
249249
$list.find('.no-select').removeClass('hide');
250-
$(input_id).val('');
250+
$.find(input_id).val('');
251251
});
252252
}
253253

@@ -450,20 +450,20 @@ export function initRepository() {
450450
// Enable or select internal/external wiki system and issue tracker.
451451
$('.enable-system').on('change', function () {
452452
if (this.checked) {
453-
$($(this).data('target')).removeClass('disabled');
454-
if (!$(this).data('context')) $($(this).data('context')).addClass('disabled');
453+
$.find($(this).data('target')).removeClass('disabled');
454+
if (!$(this).data('context')) $.find($(this).data('context')).addClass('disabled');
455455
} else {
456-
$($(this).data('target')).addClass('disabled');
457-
if (!$(this).data('context')) $($(this).data('context')).removeClass('disabled');
456+
$.find($(this).data('target')).addClass('disabled');
457+
if (!$(this).data('context')) $.find($(this).data('context')).removeClass('disabled');
458458
}
459459
});
460460
$('.enable-system-radio').on('change', function () {
461461
if (this.value === 'false') {
462-
$($(this).data('target')).addClass('disabled');
463-
if (typeof $(this).data('context') !== 'undefined') $($(this).data('context')).removeClass('disabled');
462+
$.find($(this).data('target')).addClass('disabled');
463+
if (typeof $(this).data('context') !== 'undefined') $.find($(this).data('context')).removeClass('disabled');
464464
} else if (this.value === 'true') {
465-
$($(this).data('target')).removeClass('disabled');
466-
if (typeof $(this).data('context') !== 'undefined') $($(this).data('context')).addClass('disabled');
465+
$.find($(this).data('target')).removeClass('disabled');
466+
if (typeof $(this).data('context') !== 'undefined') $.find($(this).data('context')).addClass('disabled');
467467
}
468468
});
469469
}

web_src/js/features/repo-settings.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@ export function initRepoSettingBranches() {
5252
initRepoCommonFilterSearchDropdown('.protected-branches .dropdown');
5353
$('.enable-protection, .enable-whitelist, .enable-statuscheck').on('change', function () {
5454
if (this.checked) {
55-
$($(this).data('target')).removeClass('disabled');
55+
$.find($(this).data('target')).removeClass('disabled');
5656
} else {
57-
$($(this).data('target')).addClass('disabled');
57+
$.find($(this).data('target')).addClass('disabled');
5858
}
5959
});
6060
$('.disable-whitelist').on('change', function () {
6161
if (this.checked) {
62-
$($(this).data('target')).addClass('disabled');
62+
$.find($(this).data('target')).addClass('disabled');
6363
}
6464
});
6565
}

0 commit comments

Comments
 (0)