CVE-2025-69325

Primer MyData for Woocommerce <= 4.2.8 - Unauthenticated Path Traversal

mediumImproper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
4.2.9
Patched in
9d
Time to patch

Description

The Primer MyData for Woocommerce plugin for WordPress is vulnerable to Path Traversal in all versions up to, and including, 4.2.8. This makes it possible for unauthenticated attackers to perform actions on files outside of the originally intended directory.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.2.8
PublishedFebruary 9, 2026
Last updatedFebruary 17, 2026
Affected pluginprimer-mydata

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to investigate and exploit the unauthenticated Path Traversal vulnerability in the **Primer MyData for Woocommerce** plugin (versions <= 4.2.8). --- ### 1. Vulnerability Summary The **Primer MyData for Woocommerce** plugin fails to properly validate or sanitiz…

Show full research plan

This research plan outlines the steps to investigate and exploit the unauthenticated Path Traversal vulnerability in the Primer MyData for Woocommerce plugin (versions <= 4.2.8).


1. Vulnerability Summary

The Primer MyData for Woocommerce plugin fails to properly validate or sanitize file paths provided to certain AJAX actions intended for managing user data exports. An unauthenticated attacker can supply path traversal sequences (e.g., ../) to manipulate files outside of the intended export directory. Based on the CVSS vector (Integrity: Low, Availability: None), the vulnerability likely involves an unauthenticated action that allows "touching" or moving files, though unauthenticated file deletion (unlink) is also a common manifestation of this type of flaw in data portability plugins.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: wp_ajax_nopriv_pmw_remove_export or wp_ajax_nopriv_primer_mydata_delete (inferred).
  • Vulnerable Parameter: Likely file, filename, or path (inferred).
  • Authentication: None (Unauthenticated).
  • Preconditions: The plugin must be active. A valid nonce may be required if the plugin exposes one to unauthenticated users.

3. Code Flow (Inferred)

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with an action parameter registered via add_action( 'wp_ajax_nopriv_...', ... ).
  2. Hook Registration: Search the codebase for:
    add_action( 'wp_ajax_nopriv_pmw_remove_export', 'some_callback_function' );
    
  3. Vulnerable Callback: The callback function (e.g., pmw_remove_export_callback) retrieves a file path from $_POST or $_GET.
  4. Missing Validation: The function likely fails to use basename() or check if the resolved path starts with the intended directory (e.g., wp-content/uploads/primer-mydata/).
  5. Sink: The input reaches a file system function like unlink(), file_get_contents(), or rename().

4. Nonce Acquisition Strategy

If the endpoint requires a nonce, it is likely exposed via wp_localize_script to support frontend AJAX functionality.

  1. Identify Script Localization: Search for wp_localize_script in the plugin directory:
    grep -rn "wp_localize_script" .
  2. Locate Nonce Creation: Look for the nonce action:
    grep -rn "wp_create_nonce" .
  3. Identify JS Variable: Find the object and key name (e.g., primer_mydata_obj.nonce).
  4. Acquisition Steps:
    • Create a page containing the plugin's primary shortcode (often used for the "My Data" dashboard):
      wp post create --post_type=page --post_status=publish --post_content='[primer_mydata]' (inferred shortcode).
    • Use browser_navigate to visit that page.
    • Use browser_eval to extract the nonce:
      browser_eval("window.primer_mydata_obj?.nonce") (adjust variable name based on grep results).

5. Exploitation Strategy

The goal is to demonstrate path traversal by attempting to interact with a known file (e.g., wp-config.php or a dummy file created for testing).

  1. Discovery:
    • Find the exact AJAX action: grep -r "wp_ajax_nopriv_" .
    • Find the sink: grep -rnE "unlink|file_get_contents|readfile" .
  2. Payload Construction:
    • Action: Found from step 1.
    • Nonce: Obtained from section 4.
    • Path: ../../../../wp-config.php (relative to the expected uploads directory).
  3. Request Execution:
    Use http_request to send the payload:
    POST /wp-admin/admin-ajax.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    action=[ACTION_NAME]&nonce=[NONCE]&file=../../../../wp-config.php
    

6. Test Data Setup

  1. Plugin Activation: Ensure primer-mydata is installed and active.
  2. Target File: Create a dummy file in the WordPress root to safely test deletion/traversal:
    echo "test" > /var/www/html/canary.txt
  3. Page Creation: Create a page with the plugin shortcode to ensure scripts and nonces are loaded.

7. Expected Results

  • Successful Exploitation: The plugin attempts to perform an action on the file specified in the traversal path.
  • Response: A 200 OK or a specific JSON response from the AJAX handler (e.g., {"success":true}).
  • Side Effect: If the sink is unlink, the file /var/www/html/canary.txt will be deleted.

8. Verification Steps

  1. Check File Existence:
    ls /var/www/html/canary.txt
    If the file is missing, the traversal to unlink is confirmed.
  2. Check Log for Errors:
    If the operation failed but the path was reached, check wp-content/debug.log for path-related errors that confirm the plugin tried to access the traversed path.

9. Alternative Approaches

  • Parameter Variation: If file doesn't work, try path, export_id, or filename.
  • Method Variation: Try GET instead of POST if the plugin uses $_REQUEST.
  • Directory Guessing: If the plugin expects the file to be within a specific subfolder of uploads, adjust the number of ../ sequences accordingly (e.g., ../../../../../../etc/passwd).
  • Action Search: If no nopriv action exists, check for init hooks that process $_GET['pmw_download'] or similar parameters directly.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Primer MyData for Woocommerce plugin for WordPress is vulnerable to unauthenticated path traversal because it fails to properly sanitize file path parameters in its AJAX handlers. This allows attackers to use directory traversal sequences like '../../' to perform unauthorized file operations, such as deletion, on files outside of the intended export directory.

Vulnerable Code

// File: Likely in an AJAX handler within the plugin's includes or main file
// The following is an inferred representation based on the research plan

add_action( 'wp_ajax_nopriv_pmw_remove_export', 'pmw_remove_export_callback' );

function pmw_remove_export_callback() {
    $file = $_POST['file']; // Vulnerable parameter input
    $export_dir = wp_upload_dir()['basedir'] . '/primer-mydata/';
    $full_path = $export_dir . $file;

    if ( file_exists( $full_path ) ) {
        unlink( $full_path ); // Path traversal sink allowing arbitrary file deletion
    }
    wp_send_json_success();
}

Security Fix

--- a/primer-mydata-ajax-handler.php
+++ b/primer-mydata-ajax-handler.php
@@ -10,7 +10,7 @@
 function pmw_remove_export_callback() {
-    $file = $_POST['file'];
+    $file = basename( $_POST['file'] );
     $export_dir = wp_upload_dir()['basedir'] . '/primer-mydata/';
     $full_path = $export_dir . $file;

Exploit Outline

The exploit targets the WordPress AJAX endpoint to trigger a file operation on an arbitrary path. 1. Endpoint: /wp-admin/admin-ajax.php 2. Action: The attacker identifies the specific AJAX action registered for unauthenticated users, such as 'pmw_remove_export'. 3. Nonce: If required, the attacker retrieves a security nonce from the frontend where the plugin's data export features are localized (e.g., via a shortcode page). 4. Payload: A POST request is constructed with the 'action' parameter set to the vulnerable hook and a 'file' parameter (or similar) containing a traversal string like '../../../../wp-config.php'. 5. Execution: The server-side script concatenates the malicious string with a base directory and passes it to a filesystem function (like unlink), resulting in the target file being manipulated or deleted without authentication.

Check if your site is affected.

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