This issue has been created
There are 2 updates, 1 comment.
 
 
XWiki Platform / cid:jira-generated-image-avatar-dc05ff7f-82bc-4b80-a904-059115557605 XWIKI-24469 Open

Uploading a file by drag-and-drop in the WYSIWYG editor doesn't honor the size limitation for attachments

 
View issue   ·   Add comment
 

Issue created

 
cid:jira-generated-image-avatar-2a271d13-0bcf-42d0-8365-770b8be19ccf LAMBLIN created this issue on 10/Jun/26 14:35
 
Summary: Uploading a file by drag and dropping it in edit mode will bypass the size limitation for attachments
Issue Type: cid:jira-generated-image-avatar-dc05ff7f-82bc-4b80-a904-059115557605 Bug
Affects Versions: 17.10.9
Assignee: Unassigned
Components: WYSIWYG Editor
Created: 10/Jun/26 14:35
Priority: cid:jira-generated-image-static-major-270e2dec-3bd5-4feb-8dc5-e38944605135 Major
Reporter: LAMBLIN
Description:

Steps to reproduce:

Expected result: the upload is blocked

Actual result: the upload is successful and the link in the page created

 

 
 

2 updates

 
cid:jira-generated-image-avatar-2a271d13-0bcf-42d0-8365-770b8be19ccf Changes by LAMBLIN on 10/Jun/26 14:37
 
Assignee: Vincent Massol
 
cid:jira-generated-image-avatar-025c9037-849f-4014-ab63-f12c8cb7db1d Changes by Vincent Massol on 10/Jun/26 14:37
 
Summary: Uploading a file by drag - and dropping it -drop in edit mode will bypass the WYSIWYG editor doesn't honor the size limitation for attachments
 
 

1 comment

 
cid:jira-generated-image-avatar-025c9037-849f-4014-ab63-f12c8cb7db1d Vincent Massol on 10/Jun/26 14:38
 

Analysis:

 Context
  
 The XWiki "Size Limit" feature (the upload_maxsize space/wiki preference, default 32 MB) is
 documented at AdminGuide/Attachments. The user observes that the limit is enforced when
 uploading via the classic attachment tab at the bottom of a page, but not when an image is
 drag-and-dropped into the WYSIWYG editor (which attaches the image to the page). This documents
 where the size check lives, why the two paths diverge, and a proposed fix.

 Where the size limit is actually checked

 There are two enforcement mechanisms, both reading the same upload_maxsize preference:

 1. Application-level validator — FileSizeAttachmentValidationStep
 xwiki-platform-attachment/.../validation/internal/step/FileSizeAttachmentValidationStep.java:61
 Compares wrapper.getSize() against getSpacePreferenceAsLong("upload_maxsize", 32MB) and throws
 AttachmentValidationException (HTTP 413) if exceeded. Invoked first by
 DefaultAttachmentValidator.validateAttachment() (.../internal/DefaultAttachmentValidator.java:74).
 2. Parser-level cap — ServletFileUpload.setSizeMax(uploadMaxSize) in
 oldcore/.../internal/fileupload/FileUploadUtils.java:137. Only used in the legacy
 commons-fileupload fallback branch (when the servlet container did NOT already parse the
 multipart request). On modern servlet containers (Jetty/Tomcat multipart enabled) this branch is
 never taken — see below.

 The root cause of the asymmetry

 FileUploadUtils.getFileItems() (oldcore/.../internal/fileupload/FileUploadUtils.java:83) is the
 shared entry point used by the fileupload plugin. On a modern servlet container request.getParts()
 is non-empty, so it takes the servlet-Part branch (lines 100-109):

 for (Part part : parts) {
     if (Strings.CS.startsWith(part.getName(), UploadAction.FILE_FIELD_NAME)) {  // "filepath"
         attachmentValidator.validateAttachment(new PartAttachmentAccessWrapper(part));
     }
     items.add(new PartFileItem(part));
 }

 Validation only runs for parts whose field name starts with filepath (UploadAction.FILE_FIELD_NAME).
 The parser-level setSizeMax in the else branch is skipped entirely here.

 - Attachment tab → posts to the upload action with file field filepath0 → matches the
 filter → validated → limit enforced. (UploadAction.java:67,124)
 - WYSIWYG editor → posts to the XWiki.WYSIWYG.FileUploader sheet with file field upload
 (FileUploader.xml:64,113,122). The sheet chooses one of two macros based on the
 X-XWiki-Temporary-Attachment-Support request header (FileUploader.xml:202):

   - handleTemporaryUploadRequest (header = true): calls
 temporaryAttachments.uploadTemporaryAttachment(...) →
 DefaultTemporaryAttachmentSessionsManager.uploadAttachment() which explicitly calls
 validateAttachment(...) (store-filesystem-oldcore/.../DefaultTemporaryAttachmentSessionsManager.java:144).
 → limit enforced.
   - handleUploadRequest (header absent/false): uses
 $xwiki.fileupload.getFileItemData('upload') → FileUploadPlugin.loadFileList →
 FileUploadUtils.getFileItems. Because the field name is upload (not filepath), the
 servlet-Part branch skips validation, and setSizeMax is not applied. → limit NOT enforced.

 When does the WYSIWYG fall into the non-validating handleUploadRequest path?

 The CKEditor xwiki-upload plugin sends the header from
 editor.config['xwiki-upload'].isTemporaryAttachmentSupported
 (xwiki-upload/plugin.js:223). That flag is true by default (CKEditor/ConfigSheet.xml:56,175,
 set when the temporaryAttachments script service is present), but is forced to false when:

 - Realtime / collaborative editing is active — ckeditorRealtimeAdapter.js:489 explicitly sets
 isTemporaryAttachmentSupported = false.
 - Editing an existing or new translation — FileUploader.xml:202 (!$document.isTranslation() && !$isNewTranslation).
 - The temporaryAttachments script service is unavailable (older/edge installs).

 In those situations a drag-and-dropped image is uploaded under field name upload via the legacy
 macro and bypasses the size limit entirely.

 Proposed fix

 Make the multipart-level validation field-name-agnostic so any uploaded file part is validated,
 not just filepath*. In FileUploadUtils.getFileItems() servlet-Part branch
 (oldcore/.../internal/fileupload/FileUploadUtils.java:102-107), change the gate from
 "name starts with filepath" to "the part is an actual file upload" (i.e.
 part.getSubmittedFileName() != null), which still skips plain form fields (xredirect, form_token,
 filename*, etc.) since those have no submitted filename.

 for (Part part : parts) {
     if (part.getSubmittedFileName() != null) {       // any uploaded file, regardless of field name
         attachmentValidator.validateAttachment(new PartAttachmentAccessWrapper(part));
     }
     items.add(new PartFileItem(part));
 }

 This fixes the legacy WYSIWYG handleUploadRequest path and any other consumer of the fileupload
 plugin that uses a non-filepath field name, while the temporary-attachment path keeps its existing
 explicit validation. PartAttachmentAccessWrapper.getSize() returns part.getSize()
 (oldcore/.../PartAttachmentAccessWrapper.java:54), so the size is available without consuming the
 stream.

 Files involved:
 - xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/fileupload/FileUploadUtils.java (the fix)

 Note: this changes behavior to reject oversized non-filepath uploads that previously slipped
 through; confirm with the user this is the intended scope before implementing.

 Verification

 1. Build oldcore: mvn clean install -pl xwiki-platform-core/xwiki-platform-oldcore -Plegacy,snapshot -DskipITs.
 2. Set a small upload_maxsize (e.g. 1024) in XWiki.XWikiPreferences / space WebPreferences.
 3. Attachment tab: upload a file > limit → must be rejected (regression check — already works).
 4. WYSIWYG drag-drop, realtime editing ON (forces isTemporaryAttachmentSupported=false): drop an
 image > limit → must now be rejected.
 5. WYSIWYG drag-drop, normal editing (temp attachments): drop an image > limit → still rejected.
 6. Add/extend a unit test for FileUploadUtils.getFileItems() asserting that a file part named
 upload exceeding the limit triggers validateAttachment / AttachmentValidationException.