VYPR
High severityNVD Advisory· Published Jul 31, 2024· Updated Aug 13, 2024

XWiki Platform vulnerable to Cross-site Scripting through attachment filename in uploader

CVE-2024-37900

Description

XWiki Platform is a generic wiki platform offering runtime services for applications built on top of it. When uploading an attachment with a malicious filename, malicious JavaScript code could be executed. This requires a social engineering attack to get the victim into uploading a file with a malicious name. The malicious code is solely executed during the upload and affects only the user uploading the attachment. While this allows performing actions in the name of that user, it seems unlikely that a user wouldn't notice the malicious filename while uploading the attachment. This has been patched in XWiki 14.10.21, 15.5.5, 15.10.6 and 16.0.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.xwiki.platform:xwiki-platform-web-warMaven
>= 4.2-milestone-3, < 14.10.2114.10.21
org.xwiki.platform:xwiki-platform-web-warMaven
>= 15.0-rc-1, < 15.5.515.5.5
org.xwiki.platform:xwiki-platform-web-warMaven
>= 15.6-rc-1, < 15.10.615.10.6
org.xwiki.platform:xwiki-platform-web-warMaven
>= 16.0.0-rc-1, < 16.0.016.0.0

Affected products

1

Patches

4
910a5018a500

XWIKI-19611: Improve filename escaping in attachment upload

https://github.com/xwiki/xwiki-platformpjeanjeanJan 16, 2024via ghsa
3 files changed · +26 5
  • xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/AttachmentIT.java+19 0 modified
    @@ -65,6 +65,8 @@ class AttachmentIT
     
         private static final String SECOND_ATTACHMENT = "SmallAttachment2.txt";
     
    +    private static final String ESCAPED_ATTACHMENT = "<strong>EscapedAttachment.txt";
    +
         private static final String IMAGE_ATTACHMENT = "image.gif";
     
         private static final String SMALL_SIZE_ATTACHMENT = "SmallSizeAttachment.png";
    @@ -441,6 +443,23 @@ void deleteAttachmentWithSpecialChar(TestUtils setup, TestReference testReferenc
                     basePage.getXWikiMessageContent());
         }
     
    +    @Test
    +    @Order(9)
    +    void checkEscapingInAttachmentName(TestUtils setup, TestReference testReference,
    +        TestConfiguration testConfiguration)
    +    {
    +        setup.loginAsSuperAdmin();
    +        setup.createPage(testReference, "Empty content");
    +        AttachmentsPane attachmentsPane = new AttachmentsViewPage().openAttachmentsDocExtraPane();
    +
    +        attachmentsPane.setFileToUpload(getFileToUpload(testConfiguration, ESCAPED_ATTACHMENT).getAbsolutePath());
    +        attachmentsPane.waitForUploadToFinish(ESCAPED_ATTACHMENT);
    +        attachmentsPane.clickHideProgress();
    +
    +        assertTrue(attachmentsPane.attachmentExistsByFileName(ESCAPED_ATTACHMENT));
    +        attachmentsPane.deleteAttachmentByFileByName(ESCAPED_ATTACHMENT);
    +    }
    +
         private String getAttachmentsMacroContent(DocumentReference docRef)
         {
             StringBuilder sb = new StringBuilder();
    
  • xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/resources/AttachmentIT/<strong>EscapedAttachment.txt+1 0 added
    @@ -0,0 +1 @@
    +This is an attachment whose name should be escaped.
    \ No newline at end of file
    
  • xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-war/src/main/webapp/resources/uicomponents/widgets/upload.js+6 5 modified
    @@ -124,7 +124,7 @@ var XWiki = (function(XWiki) {
     
           if (this.options.enableFileInfo) {
             statusUI.FILE_INFO   = UploadUtils.createDiv('file-info');
    -        (statusUI.FILE_NAME  = UploadUtils.createSpan('file-name', this.file.name)).title = this.file.type;
    +        (statusUI.FILE_NAME  = UploadUtils.createSpan('file-name', this.file.name.escapeHTML())).title = this.file.type;
             statusUI.FILE_SIZE   = UploadUtils.createSpan('file-size', ' (' + UploadUtils.bytesToSize(this.file.size) + ')');
             statusUI.FILE_CANCEL = UploadUtils.createButton("$services.localization.render('core.widgets.html5upload.item.cancel')", this.cancelUpload.bindAsEventListener(this));
             // TODO MIME type icon?
    @@ -295,7 +295,7 @@ var XWiki = (function(XWiki) {
             this.statusUI.FILE_CANCEL.addClassName('hidden');
           }
           this.formData.input.fire('xwiki:html5upload:message', {content: 'UPLOAD_FINISHING', type: 'inprogress', source: this,
    -        parameters : {name : this.file.name}
    +        parameters : {name : this.file.name.escapeHTML()}
           });
         },
     
    @@ -324,7 +324,7 @@ var XWiki = (function(XWiki) {
             }
           }
           this.formData.input.fire('xwiki:html5upload:message', {content: 'UPLOAD_FINISHED', type: 'done', source: this,
    -        parameters : {name : this.file.name, size : UploadUtils.bytesToSize(this.file.size)}
    +        parameters : {name : this.file.name.escapeHTML(), size : UploadUtils.bytesToSize(this.file.size)}
           });
           this.formData.input.fire('xwiki:html5upload:fileFinished', {source: this});
           clearInterval(this.timer);
    @@ -354,7 +354,8 @@ var XWiki = (function(XWiki) {
          */
         abnormalUploadFinish : function (message) {
           clearInterval(this.timer);
    -      this.formData.input.fire('xwiki:html5upload:message', {content: message, type: 'error', source: this, parameters : {name : this.file.name}});
    +      this.formData.input.fire('xwiki:html5upload:message', {content: message, type: 'error', source: this, parameters :
    +       {name : this.file.name.escapeHTML()}});
           this.formData.input.fire('xwiki:html5upload:fileFinished', {source: this});
         }
       });
    @@ -517,7 +518,7 @@ var XWiki = (function(XWiki) {
               }
             } catch (ex) {
               this.showMessage(ex, 'error', {size : UploadUtils.bytesToSize(this.options && this.options.maxFilesize),
    -                                         name : file.name, type: file.type
    +                                         name : file.name.escapeHTML(), type: file.type
               });
             }
           }
    
8b8a2d80529b

XWIKI-19611: Improve filename escaping in attachment upload

https://github.com/xwiki/xwiki-platformpjeanjeanJan 16, 2024via ghsa
3 files changed · +26 5
  • xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/AttachmentIT.java+19 0 modified
    @@ -65,6 +65,8 @@ class AttachmentIT
     
         private static final String SECOND_ATTACHMENT = "SmallAttachment2.txt";
     
    +    private static final String ESCAPED_ATTACHMENT = "<strong>EscapedAttachment.txt";
    +
         private static final String IMAGE_ATTACHMENT = "image.gif";
     
         private static final String SMALL_SIZE_ATTACHMENT = "SmallSizeAttachment.png";
    @@ -441,6 +443,23 @@ void deleteAttachmentWithSpecialChar(TestUtils setup, TestReference testReferenc
                     basePage.getXWikiMessageContent());
         }
     
    +    @Test
    +    @Order(9)
    +    void checkEscapingInAttachmentName(TestUtils setup, TestReference testReference,
    +        TestConfiguration testConfiguration)
    +    {
    +        setup.loginAsSuperAdmin();
    +        setup.createPage(testReference, "Empty content");
    +        AttachmentsPane attachmentsPane = new AttachmentsViewPage().openAttachmentsDocExtraPane();
    +
    +        attachmentsPane.setFileToUpload(getFileToUpload(testConfiguration, ESCAPED_ATTACHMENT).getAbsolutePath());
    +        attachmentsPane.waitForUploadToFinish(ESCAPED_ATTACHMENT);
    +        attachmentsPane.clickHideProgress();
    +
    +        assertTrue(attachmentsPane.attachmentExistsByFileName(ESCAPED_ATTACHMENT));
    +        attachmentsPane.deleteAttachmentByFileByName(ESCAPED_ATTACHMENT);
    +    }
    +
         private String getAttachmentsMacroContent(DocumentReference docRef)
         {
             StringBuilder sb = new StringBuilder();
    
  • xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/resources/AttachmentIT/<strong>EscapedAttachment.txt+1 0 added
    @@ -0,0 +1 @@
    +This is an attachment whose name should be escaped.
    \ No newline at end of file
    
  • xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-war/src/main/webapp/resources/uicomponents/widgets/upload.js+6 5 modified
    @@ -124,7 +124,7 @@ var XWiki = (function(XWiki) {
     
           if (this.options.enableFileInfo) {
             statusUI.FILE_INFO   = UploadUtils.createDiv('file-info');
    -        (statusUI.FILE_NAME  = UploadUtils.createSpan('file-name', this.file.name)).title = this.file.type;
    +        (statusUI.FILE_NAME  = UploadUtils.createSpan('file-name', this.file.name.escapeHTML())).title = this.file.type;
             statusUI.FILE_SIZE   = UploadUtils.createSpan('file-size', ' (' + UploadUtils.bytesToSize(this.file.size) + ')');
             statusUI.FILE_CANCEL = UploadUtils.createButton("$services.localization.render('core.widgets.html5upload.item.cancel')", this.cancelUpload.bindAsEventListener(this));
             // TODO MIME type icon?
    @@ -295,7 +295,7 @@ var XWiki = (function(XWiki) {
             this.statusUI.FILE_CANCEL.addClassName('hidden');
           }
           this.formData.input.fire('xwiki:html5upload:message', {content: 'UPLOAD_FINISHING', type: 'inprogress', source: this,
    -        parameters : {name : this.file.name}
    +        parameters : {name : this.file.name.escapeHTML()}
           });
         },
     
    @@ -324,7 +324,7 @@ var XWiki = (function(XWiki) {
             }
           }
           this.formData.input.fire('xwiki:html5upload:message', {content: 'UPLOAD_FINISHED', type: 'done', source: this,
    -        parameters : {name : this.file.name, size : UploadUtils.bytesToSize(this.file.size)}
    +        parameters : {name : this.file.name.escapeHTML(), size : UploadUtils.bytesToSize(this.file.size)}
           });
           this.formData.input.fire('xwiki:html5upload:fileFinished', {source: this});
           clearInterval(this.timer);
    @@ -354,7 +354,8 @@ var XWiki = (function(XWiki) {
          */
         abnormalUploadFinish : function (message) {
           clearInterval(this.timer);
    -      this.formData.input.fire('xwiki:html5upload:message', {content: message, type: 'error', source: this, parameters : {name : this.file.name}});
    +      this.formData.input.fire('xwiki:html5upload:message', {content: message, type: 'error', source: this, parameters :
    +       {name : this.file.name.escapeHTML()}});
           this.formData.input.fire('xwiki:html5upload:fileFinished', {source: this});
         }
       });
    @@ -517,7 +518,7 @@ var XWiki = (function(XWiki) {
               }
             } catch (ex) {
               this.showMessage(ex, 'error', {size : UploadUtils.bytesToSize(this.options && this.options.maxFilesize),
    -                                         name : file.name, type: file.type
    +                                         name : file.name.escapeHTML(), type: file.type
               });
             }
           }
    
9df46f8e5313

XWIKI-19611: Improve filename escaping in attachment upload

https://github.com/xwiki/xwiki-platformpjeanjeanJan 16, 2024via ghsa
3 files changed · +26 5
  • xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/AttachmentIT.java+19 0 modified
    @@ -65,6 +65,8 @@ class AttachmentIT
     
         private static final String SECOND_ATTACHMENT = "SmallAttachment2.txt";
     
    +    private static final String ESCAPED_ATTACHMENT = "<strong>EscapedAttachment.txt";
    +
         private static final String IMAGE_ATTACHMENT = "image.gif";
     
         private static final String SMALL_SIZE_ATTACHMENT = "SmallSizeAttachment.png";
    @@ -446,6 +448,23 @@ void deleteAttachmentWithSpecialChar(TestUtils setup, TestReference testReferenc
                     basePage.getXWikiMessageContent());
         }
     
    +    @Test
    +    @Order(9)
    +    void checkEscapingInAttachmentName(TestUtils setup, TestReference testReference,
    +        TestConfiguration testConfiguration)
    +    {
    +        setup.loginAsSuperAdmin();
    +        setup.createPage(testReference, "Empty content");
    +        AttachmentsPane attachmentsPane = new AttachmentsViewPage().openAttachmentsDocExtraPane();
    +
    +        attachmentsPane.setFileToUpload(getFileToUpload(testConfiguration, ESCAPED_ATTACHMENT).getAbsolutePath());
    +        attachmentsPane.waitForUploadToFinish(ESCAPED_ATTACHMENT);
    +        attachmentsPane.clickHideProgress();
    +
    +        assertTrue(attachmentsPane.attachmentExistsByFileName(ESCAPED_ATTACHMENT));
    +        attachmentsPane.deleteAttachmentByFileByName(ESCAPED_ATTACHMENT);
    +    }
    +
         private String getAttachmentsMacroContent(DocumentReference docRef)
         {
             StringBuilder sb = new StringBuilder();
    
  • xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/resources/AttachmentIT/<strong>EscapedAttachment.txt+1 0 added
    @@ -0,0 +1 @@
    +This is an attachment whose name should be escaped.
    \ No newline at end of file
    
  • xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-war/src/main/webapp/resources/uicomponents/widgets/upload.js+6 5 modified
    @@ -124,7 +124,7 @@ var XWiki = (function(XWiki) {
     
           if (this.options.enableFileInfo) {
             statusUI.FILE_INFO   = UploadUtils.createDiv('file-info');
    -        (statusUI.FILE_NAME  = UploadUtils.createSpan('file-name', this.file.name)).title = this.file.type;
    +        (statusUI.FILE_NAME  = UploadUtils.createSpan('file-name', this.file.name.escapeHTML())).title = this.file.type;
             statusUI.FILE_SIZE   = UploadUtils.createSpan('file-size', ' (' + UploadUtils.bytesToSize(this.file.size) + ')');
             statusUI.FILE_CANCEL = UploadUtils.createButton("$services.localization.render('core.widgets.html5upload.item.cancel')", this.cancelUpload.bindAsEventListener(this));
             // TODO MIME type icon?
    @@ -295,7 +295,7 @@ var XWiki = (function(XWiki) {
             this.statusUI.FILE_CANCEL.addClassName('hidden');
           }
           this.formData.input.fire('xwiki:html5upload:message', {content: 'UPLOAD_FINISHING', type: 'inprogress', source: this,
    -        parameters : {name : this.file.name}
    +        parameters : {name : this.file.name.escapeHTML()}
           });
         },
     
    @@ -324,7 +324,7 @@ var XWiki = (function(XWiki) {
             }
           }
           this.formData.input.fire('xwiki:html5upload:message', {content: 'UPLOAD_FINISHED', type: 'done', source: this,
    -        parameters : {name : this.file.name, size : UploadUtils.bytesToSize(this.file.size)}
    +        parameters : {name : this.file.name.escapeHTML(), size : UploadUtils.bytesToSize(this.file.size)}
           });
           this.formData.input.fire('xwiki:html5upload:fileFinished', {source: this});
           clearInterval(this.timer);
    @@ -354,7 +354,8 @@ var XWiki = (function(XWiki) {
          */
         abnormalUploadFinish : function (message) {
           clearInterval(this.timer);
    -      this.formData.input.fire('xwiki:html5upload:message', {content: message, type: 'error', source: this, parameters : {name : this.file.name}});
    +      this.formData.input.fire('xwiki:html5upload:message', {content: message, type: 'error', source: this, parameters :
    +       {name : this.file.name.escapeHTML()}});
           this.formData.input.fire('xwiki:html5upload:fileFinished', {source: this});
         }
       });
    @@ -517,7 +518,7 @@ var XWiki = (function(XWiki) {
               }
             } catch (ex) {
               this.showMessage(ex, 'error', {size : UploadUtils.bytesToSize(this.options && this.options.maxFilesize),
    -                                         name : file.name, type: file.type
    +                                         name : file.name.escapeHTML(), type: file.type
               });
             }
           }
    
6cdd69d31d6b

XWIKI-19611: Improve filename escaping in attachment upload

https://github.com/xwiki/xwiki-platformpjeanjeanJan 16, 2024via ghsa
3 files changed · +26 5
  • xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/it/org/xwiki/flamingo/test/docker/AttachmentIT.java+19 0 modified
    @@ -65,6 +65,8 @@ class AttachmentIT
     
         private static final String SECOND_ATTACHMENT = "SmallAttachment2.txt";
     
    +    private static final String ESCAPED_ATTACHMENT = "<strong>EscapedAttachment.txt";
    +
         private static final String IMAGE_ATTACHMENT = "image.gif";
     
         private static final String SMALL_SIZE_ATTACHMENT = "SmallSizeAttachment.png";
    @@ -447,6 +449,23 @@ void deleteAttachmentWithSpecialChar(TestUtils setup, TestReference testReferenc
                     basePage.getXWikiMessageContent());
         }
     
    +    @Test
    +    @Order(9)
    +    void checkEscapingInAttachmentName(TestUtils setup, TestReference testReference,
    +        TestConfiguration testConfiguration)
    +    {
    +        setup.loginAsSuperAdmin();
    +        setup.createPage(testReference, "Empty content");
    +        AttachmentsPane attachmentsPane = new AttachmentsViewPage().openAttachmentsDocExtraPane();
    +
    +        attachmentsPane.setFileToUpload(getFileToUpload(testConfiguration, ESCAPED_ATTACHMENT).getAbsolutePath());
    +        attachmentsPane.waitForUploadToFinish(ESCAPED_ATTACHMENT);
    +        attachmentsPane.clickHideProgress();
    +
    +        assertTrue(attachmentsPane.attachmentExistsByFileName(ESCAPED_ATTACHMENT));
    +        attachmentsPane.deleteAttachmentByFileByName(ESCAPED_ATTACHMENT);
    +    }
    +
         private String getAttachmentsMacroContent(DocumentReference docRef)
         {
             StringBuilder sb = new StringBuilder();
    
  • xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-test/xwiki-platform-flamingo-skin-test-docker/src/test/resources/AttachmentIT/<strong>EscapedAttachment.txt+1 0 added
    @@ -0,0 +1 @@
    +This is an attachment whose name should be escaped.
    \ No newline at end of file
    
  • xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-war/src/main/webapp/resources/uicomponents/widgets/upload.js+6 5 modified
    @@ -124,7 +124,7 @@ var XWiki = (function(XWiki) {
     
           if (this.options.enableFileInfo) {
             statusUI.FILE_INFO   = UploadUtils.createDiv('file-info');
    -        (statusUI.FILE_NAME  = UploadUtils.createSpan('file-name', this.file.name)).title = this.file.type;
    +        (statusUI.FILE_NAME  = UploadUtils.createSpan('file-name', this.file.name.escapeHTML())).title = this.file.type;
             statusUI.FILE_SIZE   = UploadUtils.createSpan('file-size', ' (' + UploadUtils.bytesToSize(this.file.size) + ')');
             statusUI.FILE_CANCEL = UploadUtils.createButton("$services.localization.render('core.widgets.html5upload.item.cancel')", this.cancelUpload.bindAsEventListener(this));
             // TODO MIME type icon?
    @@ -295,7 +295,7 @@ var XWiki = (function(XWiki) {
             this.statusUI.FILE_CANCEL.addClassName('hidden');
           }
           this.formData.input.fire('xwiki:html5upload:message', {content: 'UPLOAD_FINISHING', type: 'inprogress', source: this,
    -        parameters : {name : this.file.name}
    +        parameters : {name : this.file.name.escapeHTML()}
           });
         },
     
    @@ -324,7 +324,7 @@ var XWiki = (function(XWiki) {
             }
           }
           this.formData.input.fire('xwiki:html5upload:message', {content: 'UPLOAD_FINISHED', type: 'done', source: this,
    -        parameters : {name : this.file.name, size : UploadUtils.bytesToSize(this.file.size)}
    +        parameters : {name : this.file.name.escapeHTML(), size : UploadUtils.bytesToSize(this.file.size)}
           });
           this.formData.input.fire('xwiki:html5upload:fileFinished', {source: this});
           clearInterval(this.timer);
    @@ -354,7 +354,8 @@ var XWiki = (function(XWiki) {
          */
         abnormalUploadFinish : function (message) {
           clearInterval(this.timer);
    -      this.formData.input.fire('xwiki:html5upload:message', {content: message, type: 'error', source: this, parameters : {name : this.file.name}});
    +      this.formData.input.fire('xwiki:html5upload:message', {content: message, type: 'error', source: this, parameters :
    +       {name : this.file.name.escapeHTML()}});
           this.formData.input.fire('xwiki:html5upload:fileFinished', {source: this});
         }
       });
    @@ -517,7 +518,7 @@ var XWiki = (function(XWiki) {
               }
             } catch (ex) {
               this.showMessage(ex, 'error', {size : UploadUtils.bytesToSize(this.options && this.options.maxFilesize),
    -                                         name : file.name, type: file.type
    +                                         name : file.name.escapeHTML(), type: file.type
               });
             }
           }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

10

News mentions

0

No linked articles in our index yet.