CVE-2019-12823: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Craft CMS before 3.1.31 does not properly filter XML feeds and thus allowing XSS.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2019-06-18T13:15Z
Repository: https://github.com/craftcms/cms
Language: JavaScript
Files changed: CHANGELOG-v3.md, src/web/assets/feed/dist/FeedWidget.js, src/web/assets/feed/dist/FeedWidget.min.js, src/web/assets/feed/dist/FeedWidget.min.js.map
Commit date: 2019-06-17 11:04:23 -0700
Commit message: Fixed an XSS vulnerability

Diff: diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md
index 5c1bddd0a..748d639cc 100644
--- a/CHANGELOG-v3.md
+++ b/CHANGELOG-v3.md
@@ -15,10 +15,13 @@
 ### Fixed
 - Fixed a bug where `Craft::dd()` wouldn’t work properly if output buffering was enabled. ([#4399](https://github.com/craftcms/cms/issues/4399))
 - Fixed a bug where `Craft::alias()` wasn’t working on Windows servers. ([#4405](https://github.com/craftcms/cms/issues/4405))
 - Fixed a bug where Craft wasn't parsing the `dsn` DB connection setting properly if it was supplied.
 
+### Security
+- Fixed an XSS vulnerability.
+
 ## 3.1.30 - 2019-06-11
 
 ### Changed
 - Improved query performance. ([yiisoft/yii2#17344](https://github.com/yiisoft/yii2/pull/17344), [yiisoft/yii2#17345](https://github.com/yiisoft/yii2/pull/17345), [yiisoft/yii2#17348](https://github.com/yiisoft/yii2/pull/17348))
 - `craft\services\Elements::saveElement()` now always propagates elements regardless of the `$propagate` argument value, when saving new elements. ([#4370](https://github.com/craftcms/cms/issues/4370))
diff --git a/src/web/assets/feed/dist/FeedWidget.js b/src/web/assets/feed/dist/FeedWidget.js
index 35c4b7f13..93fe9b216 100644
--- a/src/web/assets/feed/dist/FeedWidget.js
+++ b/src/web/assets/feed/dist/FeedWidget.js
@@ -25,11 +25,15 @@
 
                         for (var i = 0; i < response.items.length; i++) {
                             var item = response.items[i],
                                 $td = $($tds[i]);
 
-                            var widgetHtml = '<a href="' + item.permalink + '" target="_blank">' + item.title + '</a> ';
+                            var widgetHtml = $('<a/>', {
+                                href: item.permalink,
+                                target: '_blank',
+                                text: item.title
+                            }).html() + ' ';
 
                             if (item.date) {
                                 widgetHtml += '<span class="light nowrap">' + item.date + '</span>';
                             }
 
diff --git a/src/web/assets/feed/dist/FeedWidget.min.js b/src/web/assets/feed/dist/FeedWidget.min.js
index 64dc1db92..06ff42c52 100644
--- a/src/web/assets/feed/dist/FeedWidget.min.js
+++ b/src/web/assets/feed/dist/FeedWidget.min.js
@@ -1,2 +1,2 @@
-!function(r){Craft.FeedWidget=Garnish.Base.extend({$widget:null,init:function(t,i,e){this.$widget=r("#widget"+t),this.$widget.addClass("loading");var a={url:i,limit:e};Craft.postActionRequest("dashboard/get-feed-items",a,r.proxy(function(t,i){if(this.$widget.removeClass("loading"),"success"===i){this.$widget.find("table").attr("dir",t.dir);for(var e=this.$widget.find("td"),a=0;a<t.items.length;a++){var s=t.items[a],d=r(e[a]),n='<a href="'+s.permalink+'" target="_blank">'+s.title+"</a> ";s.date&&(n+='<span class="light nowrap">'+s.date+"</span>"),d.html(n)}}},this))}})}(jQuery);
+!function(r){Craft.FeedWidget=Garnish.Base.extend({$widget:null,init:function(t,i,e){this.$widget=r("#widget"+t),this.$widget.addClass("loading");var a={url:i,limit:e};Craft.postActionRequest("dashboard/get-feed-items",a,r.proxy(function(t,i){if(this.$widget.removeClass("loading"),"success"===i){this.$widget.find("table").attr("dir",t.dir);for(var e=this.$widget.find("td"),a=0;a<t.items.length;a++){var s=t.items[a],d=r(e[a]),n=r("<a/>",{href:s.permalink,target:"_blank",text:s.title}).html()+" ";s.date&&(n+='<span class="light nowrap">'+s.date+"</span>"),d.html(n)}}},this))}})}(jQuery);
 //# sourceMappingURL=FeedWidget.min.js.map
\ No newline at end of file
diff --git a/src/web/assets/feed/dist/FeedWidget.min.js.map b/src/web/assets/feed/dist/FeedWidget.min.js.map
index 764ecc4ae..23b64c2d1 100644
--- a/src/web/assets/feed/dist/FeedWidget.min.js.map
+++ b/src/web/assets/feed/dist/FeedWidget.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["FeedWidget.js"],"names":["$","Craft","FeedWidget","Garnish","Base","extend","$widget","init","widgetId","url","limit","this","addClass","data","postActionRequest","proxy","response","textStatus","removeClass","find","attr","dir","$tds","i","items","length","item","$td","widgetHtml","permalink","title","date","html","jQuery"],"mappings":"CAAA,SAAUA,GAGNC,MAAMC,WAAaC,QAAQC,KAAKC,OAC5B,CACIC,QAAS,KAETC,KAAM,SAASC,EAAUC,EAAKC,GAC1BC,KAAKL,QAAUN,EAAE,UAAYQ,GAC7BG,KAAKL,QAAQM,SAAS,WAEtB,IAAIC,EAAO,CACPJ,IAAKA,EACLC,MAAOA,GAGXT,MAAMa,kBAAkB,2BAA4BD,EAAMb,EAAEe,MAAM,SAASC,EAAUC,GAGjF,GAFAN,KAAKL,QAAQY,YAAY,WAEN,YAAfD,EAA0B,CAC1BN,KAAKL,QAAQa,KAAK,SACbC,KAAK,MAAOJ,EAASK,KAI1B,IAFA,IAAIC,EAAOX,KAAKL,QAAQa,KAAK,MAEpBI,EAAI,EAAGA,EAAIP,EAASQ,MAAMC,OAAQF,IAAK,CAC5C,IAAIG,EAAOV,EAASQ,MAAMD,GACtBI,EAAM3B,EAAEsB,EAAKC,IAEbK,EAAa,YAAcF,EAAKG,UAAY,qBAAuBH,EAAKI,MAAQ,QAEhFJ,EAAKK,OACLH,GAAc,8BAAgCF,EAAKK,KAAO,WAG9DJ,EAAIK,KAAKJ,MAIlBjB,UAvCnB,CA0CGsB","file":"FeedWidget.min.js"}
\ No newline at end of file
+{"version":3,"sources":["FeedWidget.js"],"names":["$","Craft","FeedWidget","Garnish","Base","extend","$widget","init","widgetId","url","limit","this","addClass","data","postActionRequest","proxy","response","textStatus","removeClass","find","attr","dir","$tds","i","items","length","item","$td","widgetHtml","href","permalink","target","text","title","html","date","jQuery"],"mappings":"CAAA,SAAUA,GAGNC,MAAMC,WAAaC,QAAQC,KAAKC,OAC5B,CACIC,QAAS,KAETC,KAAM,SAASC,EAAUC,EAAKC,GAC1BC,KAAKL,QAAUN,EAAE,UAAYQ,GAC7BG,KAAKL,QAAQM,SAAS,WAEtB,IAAIC,EAAO,CACPJ,IAAKA,EACLC,MAAOA,GAGXT,MAAMa,kBAAkB,2BAA4BD,EAAMb,EAAEe,MAAM,SAASC,EAAUC,GAGjF,GAFAN,KAAKL,QAAQY,YAAY,WAEN,YAAfD,EAA0B,CAC1BN,KAAKL,QAAQa,KAAK,SACbC,KAAK,MAAOJ,EAASK,KAI1B,IAFA,IAAIC,EAAOX,KAAKL,QAAQa,KAAK,MAEpBI,EAAI,EAAGA,EAAIP,EAASQ,MAAMC,OAAQF,IAAK,CAC5C,IAAIG,EAAOV,EAASQ,MAAMD,GACtBI,EAAM3B,EAAEsB,EAAKC,IAEbK,EAAa5B,EAAE,OAAQ,CACvB6B,KAAMH,EAAKI,UACXC,OAAQ,SACRC,KAAMN,EAAKO,QACZC,OAAS,IAERR,EAAKS,OACLP,GAAc,8BAAgCF,EAAKS,KAAO,WAG9DR,EAAIO,KAAKN,MAIlBjB,UA3CnB,CA8CGyB","file":"FeedWidget.min.js"}
\ No newline at end of file

Vulnerable code:                             var widgetHtml = '<a href="' + item.permalink + '" target="_blank">' + item.title + '</a> ';
!function(r){Craft.FeedWidget=Garnish.Base.extend({$widget:null,init:function(t,i,e){this.$widget=r("#widget"+t),this.$widget.addClass("loading");var a={url:i,limit:e};Craft.postActionRequest("dashboard/get-feed-items",a,r.proxy(function(t,i){if(this.$widget.removeClass("loading"),"success"===i){this.$widget.find("table").attr("dir",t.dir);for(var e=this.$widget.find("td"),a=0;a<t.items.length;a++){var s=t.items[a],d=r(e[a]),n='<a href="'+s.permalink+'" target="_blank">'+s.title+"</a> ";s.date&&(n+='<span class="light nowrap">'+s.date+"</span>"),d.html(n)}}},this))}})}(jQuery);
{"version":3,"sources":["FeedWidget.js"],"names":["$","Craft","FeedWidget","Garnish","Base","extend","$widget","init","widgetId","url","limit","this","addClass","data","postActionRequest","proxy","response","textStatus","removeClass","find","attr","dir","$tds","i","items","length","item","$td","widgetHtml","permalink","title","date","html","jQuery"],"mappings":"CAAA,SAAUA,GAGNC,MAAMC,WAAaC,QAAQC,KAAKC,OAC5B,CACIC,QAAS,KAETC,KAAM,SAASC,EAAUC,EAAKC,GAC1BC,KAAKL,QAAUN,EAAE,UAAYQ,GAC7BG,KAAKL,QAAQM,SAAS,WAEtB,IAAIC,EAAO,CACPJ,IAAKA,EACLC,MAAOA,GAGXT,MAAMa,kBAAkB,2BAA4BD,EAAMb,EAAEe,MAAM,SAASC,EAAUC,GAGjF,GAFAN,KAAKL,QAAQY,YAAY,WAEN,YAAfD,EAA0B,CAC1BN,KAAKL,QAAQa,KAAK,SACbC,KAAK,MAAOJ,EAASK,KAI1B,IAFA,IAAIC,EAAOX,KAAKL,QAAQa,KAAK,MAEpBI,EAAI,EAAGA,EAAIP,EAASQ,MAAMC,OAAQF,IAAK,CAC5C,IAAIG,EAAOV,EAASQ,MAAMD,GACtBI,EAAM3B,EAAEsB,EAAKC,IAEbK,EAAa,YAAcF,EAAKG,UAAY,qBAAuBH,EAAKI,MAAQ,QAEhFJ,EAAKK,OACLH,GAAc,8BAAgCF,EAAKK,KAAO,WAG9DJ,EAAIK,KAAKJ,MAIlBjB,UAvCnB,CA0CGsB","file":"FeedWidget.min.js"}
Fixed code: ### Security
- Fixed an XSS vulnerability.

                            var widgetHtml = $('<a/>', {
                                href: item.permalink,
                                target: '_blank',
                                text: item.title
                            }).html() + ' ';
!function(r){Craft.FeedWidget=Garnish.Base.extend({$widget:null,init:function(t,i,e){this.$widget=r("#widget"+t),this.$widget.addClass("loading");var a={url:i,limit:e};Craft.postActionRequest("dashboard/get-feed-items",a,r.proxy(function(t,i){if(this.$widget.removeClass("loading"),"success"===i){this.$widget.find("table").attr("dir",t.dir);for(var e=this.$widget.find("td"),a=0;a<t.items.length;a++){var s=t.items[a],d=r(e[a]),n=r("<a/>",{href:s.permalink,target:"_blank",text:s.title}).html()+" ";s.date&&(n+='<span class="light nowrap">'+s.date+"</span>"),d.html(n)}}},this))}})}(jQuery);
{"version":3,"sources":["FeedWidget.js"],"names":["$","Craft","FeedWidget","Garnish","Base","extend","$widget","init","widgetId","url","limit","this","addClass","data","postActionRequest","proxy","response","textStatus","removeClass","find","attr","dir","$tds","i","items","length","item","$td","widgetHtml","href","permalink","target","text","title","html","date","jQuery"],"mappings":"CAAA,SAAUA,GAGNC,MAAMC,WAAaC,QAAQC,KAAKC,OAC5B,CACIC,QAAS,KAETC,KAAM,SAASC,EAAUC,EAAKC,GAC1BC,KAAKL,QAAUN,EAAE,UAAYQ,GAC7BG,KAAKL,QAAQM,SAAS,WAEtB,IAAIC,EAAO,CACPJ,IAAKA,EACLC,MAAOA,GAGXT,MAAMa,kBAAkB,2BAA4BD,EAAMb,EAAEe,MAAM,SAASC,EAAUC,GAGjF,GAFAN,KAAKL,QAAQY,YAAY,WAEN,YAAfD,EAA0B,CAC1BN,KAAKL,QAAQa,KAAK,SACbC,KAAK,MAAOJ,EAASK,KAI1B,IAFA,IAAIC,EAAOX,KAAKL,QAAQa,KAAK,MAEpBI,EAAI,EAAGA,EAAIP,EAASQ,MAAMC,OAAQF,IAAK,CAC5C,IAAIG,EAAOV,EAASQ,MAAMD,GACtBI,EAAM3B,EAAEsB,EAAKC,IAEbK,EAAa5B,EAAE,OAAQ,CACvB6B,KAAMH,EAAKI,UACXC,OAAQ,SACRC,KAAMN,EAAKO,QACZC,OAAS,IAERR,EAAKS,OACLP,GAAc,8BAAgCF,EAAKS,KAAO,WAG9DR,EAAIO,KAAKN,MAIlBjB,UA3CnB,CA8CGyB","file":"FeedWidget.min.js"}