CVE-2026-49055

Drag and Drop Multiple File Upload for Contact Form 7 <= 1.3.9.7 - Unauthenticated Stored Cross-Site Scripting

highImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
1.3.9.8
Patched in
6d
Time to patch

Description

The Drag and Drop Multiple File Upload for Contact Form 7 plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.3.9.7 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.3.9.7
PublishedJune 3, 2026
Last updatedJune 8, 2026

What Changed in the Fix

Changes introduced in v1.3.9.8

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot fulfill your request to produce a detailed exploitation research plan or functional exploit for CVE-2026-49055. My instructions prohibit the generation of actionable exploitation materials, including specific payloads, nonce acquisition strategies, or step-by-step guides for compromising sy…

Show full research plan

I cannot fulfill your request to produce a detailed exploitation research plan or functional exploit for CVE-2026-49055. My instructions prohibit the generation of actionable exploitation materials, including specific payloads, nonce acquisition strategies, or step-by-step guides for compromising systems.

Instead, I can explain the security principles involved and how developers can prevent this type of vulnerability in WordPress plugins.

Understanding Stored Cross-Site Scripting (XSS)

Stored XSS occurs when an application receives data from a user and stores it in a database without sufficient sanitization, and later renders that data in a web page without proper escaping. In the context of a WordPress file upload plugin, common injection points include:

  1. File Metadata: If the plugin stores and later displays the original filename or other metadata (like EXIF data) without sanitization, an attacker can name a file with a malicious script (e.g., <script>alert(1).jpg).
  2. AJAX Responses: If an AJAX handler returns user-provided data (such as a status message or filename) and the client-side JavaScript inserts that data into the DOM using methods like .innerHTML or .html() without escaping, a script can execute in the user's browser.
  3. Shortcode Attributes: If data stored by the plugin is displayed via a shortcode, and the shortcode's output function does not use WordPress escaping functions, it creates a persistent XSS vector.

Defensive Best Practices for WordPress Developers

To prevent Stored XSS, developers must adhere to the principle of "Sanitize on Input, Escape on Output."

1. Sanitize on Input

Always sanitize data before it is saved to the database. For filenames, WordPress provides specific functions:

// Sanitize a filename to remove dangerous characters and directory traversal attempts
$safe_filename = sanitize_file_name( $_FILES['upload-file']['name'] );

For general text fields:

  • sanitize_text_field(): Removes tags and extra whitespace.
  • wp_kses(): Allows only specific HTML tags and attributes.

2. Escape on Output

Never trust data retrieved from the database, even if it was sanitized on input. Always use context-aware escaping functions when rendering data:

  • esc_html(): Use for text appearing within HTML tags.
  • esc_attr(): Use for data appearing within HTML attributes (e.g., value="...").
  • esc_url(): Use for URLs in href or src attributes.
  • wp_json_encode(): Use when passing PHP data to JavaScript to ensure it is properly formatted and safe.

3. Secure JavaScript Implementation

When updating the DOM via JavaScript, avoid methods that interpret strings as HTML if the data is not fully trusted.

  • Safe: Use .textContent or .val() (in jQuery) which treat input as plain text.
  • Unsafe: Use .innerHTML or .html() (in jQuery) unless the data has been explicitly sanitized for HTML context.

For more information on securing WordPress plugins, I recommend reviewing the WordPress Plugin Handbook on Security and the OWASP XSS Prevention Cheat Sheet.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Drag and Drop Multiple File Upload for Contact Form 7 plugin allows unauthenticated users to upload files with malicious names containing JavaScript. Because the plugin's client-side scripts fail to escape these filenames before inserting them into the page's HTML via innerHTML, an attacker can execute arbitrary web scripts in the browser of any user (including administrators) who interacts with the upload area or views the submission.

Vulnerable Code

// assets/js/codedropz-uploader-min.js (~ line 133 in version 1.3.9.7)
v={createProgressBar:function(e){var t=m.querySelector(".codedropz-upload-handler"),a="dnd-file-"+Math.random().toString(36).substr(2,9),r=`
                    <div class="dnd-upload-image">
                        <span class="file"></span>
                    </div>
                    <div class="dnd-upload-details">
                        <span class="name"><span>${e.name}</span><em>(${v.bytesToSize(e.size)})</em></span>
                        <a href="#" title="${dnd_cf7_uploader.drag_n_drop_upload.delete.title}" class="remove-file" data-storage="${s}">
                        <span class="dnd-icon-remove"></span>
                        </a>
                        <span class="dnd-progress-bar"><span></span></span>
                    </div>
                `,d=document.createElement("div");return d.id=a,d.className="dnd-upload-status",d.innerHTML=r,t.parentNode.insertBefore(d,t.nextSibling),a}

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/drag-and-drop-multiple-file-upload-contact-form-7/1.3.9.7/assets/js/codedropz-uploader-min.js	2026-04-17 04:16:40.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/drag-and-drop-multiple-file-upload-contact-form-7/1.3.9.8/assets/js/codedropz-uploader-min.js	2026-05-26 10:13:30.000000000 +0000
@@ -2,173 +2,32 @@
  * CodeDropz Uploader
  * Copyright 2018 Glen Mongaya
  * CodeDrop Drag&Drop Uploader
- * @version 1.3.9.7
+ * @version 1.3.9.8
  * @author CodeDropz, Glen Don L. Mongaya
  * @license The MIT License (MIT)
  */
 
 // CodeDropz Drag and Drop Plugin
-!function(){let e=function(e){let t=document.querySelector("form.wpcf7-form");if(t){let a=new FormData;a.append("action","_wpcf7_check_nonce"),a.append("_ajax_nonce",dnd_cf7_uploader.ajax_nonce),fetch(dnd_cf7_uploader.ajax_url,{method:"POST",body:a}).then(e=>e.json()).then(({data:e,success:t})=>t&&(dnd_cf7_uploader.ajax_nonce=e)).catch(console.error)}let r=function(e=20){let t=new Uint8Array(16);crypto.getRandomValues(t),t[6]=15&t[6]|64,t[8]=63&t[8]|128;let a=Array.from(t,e=>e.toString(16).padStart(2,"0")).join("");return a.replace(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/,"$1-$2-$3-$4-$5")};var d=this;let o={handler:d,color:"#000",background:"",server_max_error:"Uploaded file exceeds the maximum upload size of your server.",max_file:d.dataset.max?d.dataset.max:10,max_upload_size:d.dataset.limit?d.dataset.limit:"10485760",supported_type:d.dataset.type?d.dataset.type:"jpg|jpeg|JPG|png|gif|pdf|doc|docx|ppt|pptx|odt|avi|ogg|m4a|mov|mp3|mp4|mpg|wav|wmv|xls",text:"Drag & Drop Files Here",separator:"or",button_text:"Browse Files",on_success:""},n=Object.assign({},o,e);var s=d.dataset.name+"_count_files";localStorage.setItem(s,1);var l=dnd_upload_cf7_unique_id(),p=l?localStorage.getItem("dnd_cf7_token_"+l):null;l&&p||(l=r(),p=r(),localStorage.setItem("dnd_wpcf7_session_id",JSON.stringify({value:l,savedAt:Date.now()})),localStorage.setItem("dnd_cf7_token_"+l,p));let i=`
+!function(){let e=function(e){let t=document.querySelector("form.wpcf7-form");if(t){let r=new FormData;r.append("action","_wpcf7_check_nonce"),r.append("_ajax_nonce",dnd_cf7_uploader.ajax_nonce),fetch(dnd_cf7_uploader.ajax_url,{method:"POST",body:r}).then(e=>e.json()).then(({data:e,success:t})=>t&&(dnd_cf7_uploader.ajax_nonce=e)).catch(console.error)}let a=function(e=20){let t=new Uint8Array(16);crypto.getRandomValues(t),t[6]=15&t[6]|64,t[8]=63&t[8]|128;let r=Array.from(t,e=>e.toString(16).padStart(2,"0")).join("");return r.replace(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/,"$1-$2-$3-$4-$5")};var n=this;let o={handler:n,color:"#000",background:"",server_max_error:"Uploaded file exceeds the maximum upload size of your server.",max_file:n.dataset.max?parseInt(n.dataset.max):10,max_upload_size:n.dataset.limit?n.dataset.limit:"10485760",supported_type:n.dataset.type?n.dataset.type:"jpg|jpeg|JPG|png|gif|pdf|doc|docx|ppt|pptx|odt|avi|ogg|m4a|mov|mp3|mp4|mpg|wav|wmv|xls",text:"Drag & Drop Files Here",separator:"or",button_text:"Browse Files",on_success:""},d=Object.assign({},o,e);var s=n.dataset.name+"_count_files";localStorage.setItem(s,1);var l=dnd_upload_cf7_unique_id(),p=l?localStorage.getItem("dnd_cf7_token_"+l):null;l&&p||(l=a(),p=a(),localStorage.setItem("dnd_wpcf7_session_id",JSON.stringify({value:l,savedAt:Date.now()})),localStorage.setItem("dnd_cf7_token_"+l,p));let c=`

Exploit Outline

1. Locate a Contact Form 7 form on a target WordPress site that utilizes the 'Drag and Drop Multiple File Upload' field type ([mfile]). 2. Prepare a benign file (e.g., a small image) and rename it to include a JavaScript payload, such as: <img src=x onerror=alert(document.domain)>.png. 3. As an unauthenticated user, either drag the file onto the upload area or use the browse button to select it. 4. The plugin's JavaScript immediately processes the file metadata to create a status indicator. It uses a template literal to insert the filename into an HTML string and then sets the innerHTML of a new status <div> to that string. 5. The payload executes immediately in the browser. If the filename is persisted and later viewed by an administrator (e.g., via a submission management plugin like Flamingo), the script will execute in the administrative context.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.