Skip to content

Commit

Permalink
[SECURITY] Prevent XSS in modal component and PageTree
Browse files Browse the repository at this point in the history
Resolves: #84190
Releases: master, 8.7, 7.6
Security-Commit: 0aaf266ae75d04efc6a943f9414448d5c2787309
Security-Bulletin: TYPO3-CORE-SA-2018-007
Change-Id: Ic5beb5217326d8f3d72445d4bf9cc7ace705a5a0
Reviewed-on: https://review.typo3.org/59101
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
  • Loading branch information
NeoBlack authored and ohader committed Dec 11, 2018
1 parent a32a9a7 commit 02cd5c9
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 22 deletions.
25 changes: 16 additions & 9 deletions typo3/sysext/backend/Resources/Private/TypeScript/Modal.ts
Expand Up @@ -16,6 +16,7 @@ import 'bootstrap';
import * as $ from 'jquery';
import Icons = require('./Icons');
import Severity = require('./Severity');
import SecurityUtility = require('TYPO3/CMS/Core/SecurityUtility');

enum Identifiers {
modal = '.t3js-modal',
Expand Down Expand Up @@ -116,7 +117,10 @@ class Modal {
ajaxTarget: null
};

constructor() {
private readonly securityUtility: SecurityUtility;

constructor(securityUtility: SecurityUtility) {
this.securityUtility = securityUtility;
$(document).on('modal-dismiss', this.dismiss);
this.initializeMarkupTrigger(document);
}
Expand Down Expand Up @@ -250,9 +254,15 @@ class Modal {
configuration.title = typeof configuration.title === 'string'
? configuration.title
: this.defaultConfiguration.title;
configuration.content = typeof configuration.content === 'string' || typeof configuration.content === 'object'
? configuration.content
: this.defaultConfiguration.content;
if (typeof configuration.content === 'string') {
// A string means, no markup allowed, let's ensure this
configuration.content = this.securityUtility.encodeHtml(configuration.content);
} else if (typeof configuration.content === 'object') {
// An object means, a valid jQuery object with markup, let's get the markup
configuration.content = configuration.content.html();
} else {
configuration.content = this.defaultConfiguration.content;
}
configuration.severity = typeof configuration.severity !== 'undefined'
? configuration.severity
: this.defaultConfiguration.severity;
Expand Down Expand Up @@ -375,10 +385,7 @@ class Modal {
});
} else {
if (typeof configuration.content === 'string') {
// we need html, check if we have to wrap content in <p>
if (!/^<[a-z][\s\S]*>/i.test(configuration.content)) {
configuration.content = $('<p />').html(configuration.content);
}
configuration.content = $('<p />').html(configuration.content);
}
currentModal.find(Identifiers.body).append(configuration.content);
}
Expand Down Expand Up @@ -488,7 +495,7 @@ try {
}

if (!modalObject) {
modalObject = new Modal();
modalObject = new Modal(new SecurityUtility());

// expose as global object
TYPO3.Modal = modalObject;
Expand Down
2 changes: 1 addition & 1 deletion typo3/sysext/backend/Resources/Public/JavaScript/Modal.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -20,10 +20,13 @@ define([
'jquery',
'd3',
'TYPO3/CMS/Backend/Modal',
'TYPO3/CMS/Backend/Severity'
], function($, d3, Modal, Severity) {
'TYPO3/CMS/Backend/Severity',
'TYPO3/CMS/Core/SecurityUtility'
], function($, d3, Modal, Severity, SecurityUtility) {
'use strict';

var securityUtility = new SecurityUtility();

/**
* PageTreeDragDrop class
*
Expand Down Expand Up @@ -841,16 +844,25 @@ define([
* @returns {String}
*/
template: function(icon, name) {
return '<div class="node-dd node-dd--nodrop">' +
'<div class="node-dd__ctrl-icon">' +
'</div>' +
'<div class="node-dd__text">' +
'<span class="node-dd__icon">' +
'<svg aria-hidden="true" width="16px" height="16px"><use xlink:href="' + icon + '"/></svg>' +
'</span>' +
'<span class="node-dd__name">' + name + '</span>' +
'</div>' +
'</div>';
return $('<div>').append(
$('<div>', {'class': 'node-dd node-dd--nodrop'}).append(
$('<div>', {'class': 'node-dd__ctrl-icon'}),
$('<div>', {'class': 'node-dd__text'}).append(
$('<span>', {'class': 'node-dd__icon'}).append(
$('<svg>', {
'aria-hidden': 'true',
'width': '16px',
'height': '16px'
}).append(
$('<use>', {
'xlink:href': icon
})
)
),
$('<span>', {'class': 'node-dd__name'}).text(securityUtility.encodeHtml(name))
)
)
).html();
}
};

Expand Down

0 comments on commit 02cd5c9

Please sign in to comment.