Skip to content

Commit

Permalink
replace $.parseHTML() to prevent XSS
Browse files Browse the repository at this point in the history
  • Loading branch information
mvorisek committed Jan 24, 2024
1 parent 8a088fe commit 92d04b5
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 17 deletions.
9 changes: 5 additions & 4 deletions js/src/services/api.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,17 @@ class ApiService {
throw new Error('Target DOM element not found');
}

const responseBody = new DOMParser().parseFromString('<body>' + response.html.trim() + '</body>', 'text/html').body;
let responseBody = new DOMParser().parseFromString('<body>' + response.html.trim() + '</body>', 'text/html').body;
const responseElement = responseBody.childNodes[0];
if (responseBody.childNodes.length !== 1 || responseElement.id !== response.id) {
throw new Error('Unexpected HTML response');
}
responseBody = null;

// prevent modal duplication
const modelsContainer = $('.ui.dimmer.modals.page')[0];
$($.parseHTML(response.html)).find('.ui.modal[id]').each((i, e) => {
$(modelsContainer).find('#' + e.id).remove();
const $modalsContainers = $('body > .ui.dimmer.modals.page').add('body > .atk-side-panels');
$(responseElement).find('.ui.modal[id]').add('.atk-right-panel[id]').each((i, e) => {
$modalsContainers.find('#' + e.id).remove();
});

if ($target.hasClass('ui modal') || $target.hasClass('atk-right-panel')) {
Expand Down
9 changes: 6 additions & 3 deletions js/src/services/modal.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,12 @@ class ModalService {
method: 'GET',
obj: $content,
onComplete: function (response, content) {
const modelsContainer = $('.ui.dimmer.modals.page')[0];
$($.parseHTML(response.html)).find('.ui.modal[id]').each((i, e) => {
$(modelsContainer).find('#' + e.id).remove();
// prevent modal duplication
// TODO deduplicate in favor of api.service.js code only
const responseBody = new DOMParser().parseFromString('<body>' + response.html.trim() + '</body>', 'text/html').body;
const $modalsContainers = $('body > .ui.dimmer.modals.page').add('body > .atk-side-panels');
$(responseBody.childNodes[0]).find('.ui.modal[id]').add('.atk-right-panel[id]').each((i, e) => {
$modalsContainers.find('#' + e.id).remove();
});

const result = content.html(response.html);
Expand Down
18 changes: 11 additions & 7 deletions public/js/atkjs-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -2016,16 +2016,17 @@ class ApiService {
if ($target.length !== 1) {
throw new Error('Target DOM element not found');
}
const responseBody = new DOMParser().parseFromString('<body>' + response.html.trim() + '</body>', 'text/html').body;
let responseBody = new DOMParser().parseFromString('<body>' + response.html.trim() + '</body>', 'text/html').body;
const responseElement = responseBody.childNodes[0];
if (responseBody.childNodes.length !== 1 || responseElement.id !== response.id) {
throw new Error('Unexpected HTML response');
}
responseBody = null;

// prevent modal duplication
const modelsContainer = external_jquery__WEBPACK_IMPORTED_MODULE_5___default()('.ui.dimmer.modals.page')[0];
external_jquery__WEBPACK_IMPORTED_MODULE_5___default()(external_jquery__WEBPACK_IMPORTED_MODULE_5___default().parseHTML(response.html)).find('.ui.modal[id]').each((i, e) => {
external_jquery__WEBPACK_IMPORTED_MODULE_5___default()(modelsContainer).find('#' + e.id).remove();
const $modalsContainers = external_jquery__WEBPACK_IMPORTED_MODULE_5___default()('body > .ui.dimmer.modals.page').add('body > .atk-side-panels');
external_jquery__WEBPACK_IMPORTED_MODULE_5___default()(responseElement).find('.ui.modal[id]').add('.atk-right-panel[id]').each((i, e) => {
$modalsContainers.find('#' + e.id).remove();
});
if ($target.hasClass('ui modal') || $target.hasClass('atk-right-panel')) {
external_jquery__WEBPACK_IMPORTED_MODULE_5___default().each([...$target[0].childNodes], (i, node) => {
Expand Down Expand Up @@ -2621,9 +2622,12 @@ class ModalService {
method: 'GET',
obj: $content,
onComplete: function (response, content) {
const modelsContainer = external_jquery__WEBPACK_IMPORTED_MODULE_5___default()('.ui.dimmer.modals.page')[0];
external_jquery__WEBPACK_IMPORTED_MODULE_5___default()(external_jquery__WEBPACK_IMPORTED_MODULE_5___default().parseHTML(response.html)).find('.ui.modal[id]').each((i, e) => {
external_jquery__WEBPACK_IMPORTED_MODULE_5___default()(modelsContainer).find('#' + e.id).remove();
// prevent modal duplication
// TODO deduplicate in favor of api.service.js code only
const responseBody = new DOMParser().parseFromString('<body>' + response.html.trim() + '</body>', 'text/html').body;
const $modalsContainers = external_jquery__WEBPACK_IMPORTED_MODULE_5___default()('body > .ui.dimmer.modals.page').add('body > .atk-side-panels');
external_jquery__WEBPACK_IMPORTED_MODULE_5___default()(responseBody.childNodes[0]).find('.ui.modal[id]').add('.atk-right-panel[id]').each((i, e) => {
$modalsContainers.find('#' + e.id).remove();
});
const result = content.html(response.html);
if (result.length === 0) {
Expand Down
2 changes: 1 addition & 1 deletion public/js/atkjs-ui.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/js/atkjs-ui.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/js/atkjs-ui.min.js.map

Large diffs are not rendered by default.

0 comments on commit 92d04b5

Please sign in to comment.