Skip to content

Commit f9b4efd

Browse files
Forbid HTML injection using jQuery (#29843)
See https://github.com/wikimedia/eslint-plugin-no-jquery/blob/master/docs/rules/no-append-html.md Tested the following components and they work as before: - notification table - issue author dropdown - comment edit box attachments div Signed-off-by: Yarden Shoham <[email protected]> Co-authored-by: Giteabot <[email protected]>
1 parent c6e5ec5 commit f9b4efd

File tree

5 files changed

+12
-9
lines changed

5 files changed

+12
-9
lines changed

.eslintrc.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ rules:
400400
no-jquery/no-and-self: [2]
401401
no-jquery/no-animate-toggle: [2]
402402
no-jquery/no-animate: [2]
403-
no-jquery/no-append-html: [0]
403+
no-jquery/no-append-html: [2]
404404
no-jquery/no-attr: [0]
405405
no-jquery/no-bind: [2]
406406
no-jquery/no-box-model: [2]

web_src/js/features/notification.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ async function updateNotificationCountWithCallback(callback, timeout, lastCount)
143143
}
144144

145145
async function updateNotificationTable() {
146-
const $notificationDiv = $('#notification_div');
147-
if ($notificationDiv.length > 0) {
146+
const notificationDiv = document.getElementById('notification_div');
147+
if (notificationDiv) {
148148
try {
149149
const params = new URLSearchParams(window.location.search);
150150
params.set('div-only', true);
@@ -158,7 +158,7 @@ async function updateNotificationTable() {
158158

159159
const data = await response.text();
160160
if ($(data).data('sequence-number') === notificationSequenceNumber) {
161-
$notificationDiv.replaceWith(data);
161+
notificationDiv.outerHTML = data;
162162
initNotificationsTable();
163163
}
164164
} catch (error) {

web_src/js/features/repo-issue-list.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ function initRepoIssueListAuthorDropdown() {
125125
if (newMenuHtml) {
126126
const $newMenuItems = $(newMenuHtml);
127127
$newMenuItems.addClass('dynamic-item');
128-
$menu.append('<div class="divider dynamic-item"></div>', ...$newMenuItems);
128+
const div = document.createElement('div');
129+
div.classList.add('divider', 'dynamic-item');
130+
$menu[0].append(div, ...$newMenuItems);
129131
}
130132
$searchDropdown.dropdown('refresh');
131133
// defer our selection to the next tick, because dropdown will set the selection item after this `menu` function

web_src/js/features/repo-legacy.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,13 +436,12 @@ async function onEditContent(event) {
436436
const $content = $segment;
437437
if (!$content.find('.dropzone-attachments').length) {
438438
if (data.attachments !== '') {
439-
$content.append(`<div class="dropzone-attachments"></div>`);
440-
$content.find('.dropzone-attachments').replaceWith(data.attachments);
439+
$content[0].append(data.attachments);
441440
}
442441
} else if (data.attachments === '') {
443442
$content.find('.dropzone-attachments').remove();
444443
} else {
445-
$content.find('.dropzone-attachments').replaceWith(data.attachments);
444+
$content.find('.dropzone-attachments')[0].outerHTML = data.attachments;
446445
}
447446
if (dz) {
448447
dz.emit('submit');

web_src/js/modules/fomantic/dropdown.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ function delegateOne($dropdown) {
7272
dropdownTemplates.menu = function(response, fields, preserveHTML, className) {
7373
// when the dropdown menu items are loaded from AJAX requests, the items are created dynamically
7474
const menuItems = dropdownTemplatesMenuOld(response, fields, preserveHTML, className);
75-
const $wrapper = $('<div>').append(menuItems);
75+
const div = document.createElement('div');
76+
div.innerHTML = menuItems;
77+
const $wrapper = $(div);
7678
const $items = $wrapper.find('> .item');
7779
$items.each((_, item) => updateMenuItem($dropdown[0], item));
7880
$dropdown[0][ariaPatchKey].deferredRefreshAriaActiveItem();

0 commit comments

Comments
 (0)