diff --git a/CHANGES.md b/CHANGES.md index a1539a11d55..555d4a17158 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Fixed Issues: * [#11574](http://dev.ckeditor.com/ticket/11574): Fixed *Backspace* destroying DOM structure if inline editable is placed in list item. * [#11603](http://dev.ckeditor.com/ticket/11603): Fixed: [Tableresize](http://ckeditor.com/addon/tableresize) attaches to tables outside of editable. * [#9205](http://dev.ckeditor.com/ticket/9205), [#7805](http://dev.ckeditor.com/ticket/7805), [#8216](http://dev.ckeditor.com/ticket/8216): Fixed: `{cke_protected_1}` appearing in data in various cases where HTML comments are placed next to `"` or `'`. +* [#11635](http://dev.ckeditor.com/ticket/11635): Fixed: Some attributes are not protected before content is passed through fix bin. ## CKEditor 4.3.3 diff --git a/core/htmldataprocessor.js b/core/htmldataprocessor.js index e00c0a833c0..6da460db72b 100644 --- a/core/htmldataprocessor.js +++ b/core/htmldataprocessor.js @@ -81,6 +81,10 @@ // eat it up. (#5789) data = protectPreFormatted( data ); + // There are attributes which may execute JavaScript code inside fixBin. + // Encode them greedily. They will be unprotected right after getting HTML from fixBin. (#10) + data = protectInsecureAttributes( data ); + var fixBin = evtData.context || editor.editable().getName(), isPre; @@ -99,7 +103,7 @@ data = el.getHtml().substr( 1 ); // Restore shortly protected attribute names. - data = data.replace( new RegExp( ' data-cke-' + CKEDITOR.rnd + '-', 'ig' ), ' ' ); + data = data.replace( new RegExp( 'data-cke-' + CKEDITOR.rnd + '-', 'ig' ), '' ); isPre && ( data = data.replace( /^
|<\/pre>$/gi, '' ) );
 
@@ -824,6 +828,14 @@
 		} );
 	}
 
+	// Replace all "on\w{3,}" strings which are not:
+	// * opening tags - e.g. ` (tested in "false positive 1"),
+	// * part of other attribute - e.g. `data-onfoo` or `fonfoo`.
+	function protectInsecureAttributes( html ) {
+		return html.replace( /([^a-z0-9<\-])(on\w{3,})(?!>)/gi, '$1data-cke-' + CKEDITOR.rnd + '-$2' );
+	}
+
 	function unprotectRealComments( html ) {
 		return html.replace( //g, function( match, data ) {
 			return decodeURIComponent( data );