CVE-2022-31048: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: TYPO3 is an open source web content management system. Prior to versions 8.7.47 ELTS, 9.5.34 ELTS, 10.4.29, and 11.5.11, the Form Designer backend module of the Form Framework is vulnerable to cross-site scripting. A valid backend user account with access to the form module is needed to exploit this vulnerability. TYPO3 versions 8.7.47 ELTS, 9.5.34 ELTS, 10.4.29, and 11.5.11 contain a fix for the problem.
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: 5.4
Published: 2022-06-14T21:15Z
Repository: https://github.com/TYPO3/typo3
Language: JavaScript
Files changed: typo3/sysext/form/Resources/Public/JavaScript/backend/form-editor/stage-component.js
Commit date: 2022-06-14 09:17:59 +0200
Commit message: [SECURITY] Ensure text preview of multivalue items in form editor

Multivalue items in the form editor user interface were previewed
as HTML, but should be treated as scalar text only.

Resolves: #96743
Releases: main, 11.5, 10.4
Change-Id: I5e8dab26119490ecf19ac5d48c2bc7a5a00daaad
Security-Bulletin: TYPO3-CORE-SA-2022-003
Security-References: CVE-2022-31048
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/73297
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>

Diff: diff --git a/typo3/sysext/form/Resources/Public/JavaScript/backend/form-editor/stage-component.js b/typo3/sysext/form/Resources/Public/JavaScript/backend/form-editor/stage-component.js
index 4cac39607c9..a7814784129 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/backend/form-editor/stage-component.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/backend/form-editor/stage-component.js
@@ -511,14 +511,14 @@ function factory($, Helper, Icons) {
      * @param string title
      * @return void
      */
     function setStageHeadline(title) {
       if (getUtility().isUndefinedOrNull(title)) {
-        title = buildTitleByFormElement();
+        title = buildTitleByFormElement().text();
       }
 
-      $(getHelper().getDomElementDataIdentifierSelector('stageHeadline')).html(title);
+      $(getHelper().getDomElementDataIdentifierSelector('stageHeadline')).text(title);
     };
 
     /**
      * @public
      *
@@ -979,14 +979,14 @@ function factory($, Helper, Icons) {
           .append($(icon).addClass(getHelper().getDomElementClassName('icon')));
       });
 
       getHelper()
         .getTemplatePropertyDomElement('_type', template)
-        .append(getFormElementDefinition(formElement, 'label'));
+        .append(document.createTextNode(getFormElementDefinition(formElement, 'label')));
       getHelper()
         .getTemplatePropertyDomElement('_identifier', template)
-        .append(formElement.get('identifier'));
+        .append(document.createTextNode(formElement.get('identifier')));
     };
 
     /**
      * @public
      *
@@ -1027,11 +1027,11 @@ function factory($, Helper, Icons) {
               .getFormEditorDefinition('validators', validators[i]['identifier']);
             rowTemplate = $($(validatorsTemplateContent).clone());
 
             getHelper()
               .getTemplatePropertyDomElement('_label', rowTemplate)
-              .append(collectionElementConfiguration['label']);
+              .append(document.createTextNode(collectionElementConfiguration['label']));
             $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template))
               .append(rowTemplate.html());
           }
 
           if (validatorsCountWithoutRequired > 0) {
@@ -1087,11 +1087,11 @@ function factory($, Helper, Icons) {
             isPreselected = true;
             break;
           }
         }
 
-        getHelper().getTemplatePropertyDomElement('_label', rowTemplate).append(label);
+        getHelper().getTemplatePropertyDomElement('_label', rowTemplate).append(document.createTextNode(label));
 
         if (isPreselected) {
           getHelper().getTemplatePropertyDomElement('_label', rowTemplate).addClass(
             getHelper().getDomElementClassName('selected')
           );

Vulnerable code:         title = buildTitleByFormElement();
      $(getHelper().getDomElementDataIdentifierSelector('stageHeadline')).html(title);
        .append(getFormElementDefinition(formElement, 'label'));
        .append(formElement.get('identifier'));
              .append(collectionElementConfiguration['label']);
        getHelper().getTemplatePropertyDomElement('_label', rowTemplate).append(label);
Fixed code:         title = buildTitleByFormElement().text();
      $(getHelper().getDomElementDataIdentifierSelector('stageHeadline')).text(title);
        .append(document.createTextNode(getFormElementDefinition(formElement, 'label')));
        .append(document.createTextNode(formElement.get('identifier')));
              .append(document.createTextNode(collectionElementConfiguration['label']));
        getHelper().getTemplatePropertyDomElement('_label', rowTemplate).append(document.createTextNode(label));