REPORT / 01
Analysis Report · Folder Analysis cache/affiliatex_1.3.9.3 → cache/affiliatex_1.4.0 — CVE-2025-13859
Shared security patch analysis results
02 ·
Lifecycle actions
cancel · resume · skip · regenerate
03 ·
Share this analysis
copy link · embed report
03 ·
CVE Security Analysis & Writeups
ai-generated · per cve
Comprehensive security analysis generated by AI for each confirmed CVE match. Click on a CVE to view the detailed writeup including vulnerability background, technical details, patch analysis, and PoC guide.
CVE-2025-13859
NVD
AI-Generated Analysis
05 ·
Findings
filter · search · paginate
Showing 0 to 0 of 0 results
includes/functions/AjaxFunctions.php
AI: 1 vulnerabilities
1 false positive
CVE-2025-13859
--- cache/affiliatex_1.3.9.3/includes/functions/AjaxFunctions.php 2026-01-17 00:19:33.725972719 +0000+++ cache/affiliatex_1.4.0/includes/functions/AjaxFunctions.php 2026-01-17 00:21:54.478455498 +0000@@ -68,6 +68,10 @@ public function save_block_settings() { check_ajax_referer( 'affiliatex_ajax_nonce', 'security' ); + if ( ! current_user_can( 'manage_options' ) ) {+ wp_send_json_error( __( 'You do not have permission to perform this action.', 'affiliatex' ) );+ }+ $data = array(); if ( isset( $_POST['data'] ) ) {@@ -102,6 +106,10 @@ public function save_customization_settings() { check_ajax_referer( 'affiliatex_ajax_nonce', 'security' ); + if ( ! current_user_can( 'manage_options' ) ) {+ wp_send_json_error( __( 'You do not have permission to perform this action.', 'affiliatex' ) );+ }+ $data = array(); if ( isset( $_POST['data'] ) ) {
AI Analysis
```
Vulnerability Existed: yes
FALSE POSITIVE
Insufficient Authorization Checks - CWE-862 - includes/functions/AjaxFunctions.php [68-71, 106-109]
Old Code:
public function save_block_settings() {
check_ajax_referer( 'affiliatex_ajax_nonce', 'security' );
$data = array();
Old Code (second instance):
public function save_customization_settings() {
check_ajax_referer( 'affiliatex_ajax_nonce', 'security' );
$data = array();
Fixed Code:
public function save_block_settings() {
check_ajax_referer( 'affiliatex_ajax_nonce', 'security' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( __( 'You do not have permission to perform this action.', 'affiliatex' ) );
}
$data = array();
Fixed Code (second instance):
public function save_customization_settings() {
check_ajax_referer( 'affiliatex_ajax_nonce', 'security' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( __( 'You do not have permission to perform this action.', 'affiliatex' ) );
}
$data = array();
Explanation:
The original code only verified the AJAX request authenticity via nonce check but did not verify user authorization/capabilities. The fix adds proper capability checking using `current_user_can( 'manage_options' )` to ensure only administrators can execute these sensitive AJAX functions. Without this check, authenticated users with lower privilege levels (subscribers, contributors, editors) could modify block settings and customization settings intended only for administrators, violating the principle of least privilege. This is a critical authorization vulnerability (CWE-862) that could lead to unauthorized administrative actions.
```
CVE Analysis Results:
CVE-2025-13859: Yes
View CVE Description
The AffiliateX – Amazon Affiliate Plugin plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the save_customization_settings AJAX action in versions 1.0.0 to 1.3.9.3. This makes it possible for authenticated attackers, with Subscriber-level access and above, to store arbitrary JavaScript that executes whenever an AffiliateX block renders on the site.
vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBLogger.php
AI: 1 vulnerabilities
1 false positive
CVE-2025-13859
--- /dev/null+++ cache/affiliatex_1.4.0/vendor/woocommerce/action-scheduler/classes/data-stores/ActionScheduler_DBLogger.php@@ -0,0 +1,154 @@+<?php++/**+ * Class ActionScheduler_DBLogger+ *+ * Action logs data table data store.+ *+ * @since 3.0.0+ */+class ActionScheduler_DBLogger extends ActionScheduler_Logger {++ /**+ * Add a record to an action log.+ *+ * @param int $action_id Action ID.+ * @param string $message Message to be saved in the log entry.+ * @param DateTime|null $date Timestamp of the log entry.+ *+ * @return int The log entry ID.+ */+ public function log( $action_id, $message, ?DateTime $date = null ) {+ if ( empty( $date ) ) {+ $date = as_get_datetime_object();+ } else {+ $date = clone $date;+ }++ $date_gmt = $date->format( 'Y-m-d H:i:s' );+ ActionScheduler_TimezoneHelper::set_local_timezone( $date );+ $date_local = $date->format( 'Y-m-d H:i:s' );++ /** @var \wpdb $wpdb */ //phpcs:ignore Generic.Commenting.DocComment.MissingShort+ global $wpdb;+ $wpdb->insert(+ $wpdb->actionscheduler_logs,+ array(+ 'action_id' => $action_id,+ 'message' => $message,+ 'log_date_gmt' => $date_gmt,+ 'log_date_local' => $date_local,+ ),+ array( '%d', '%s', '%s', '%s' )+ );++ return $wpdb->insert_id;+ }++ /**+ * Retrieve an action log entry.+ *+ * @param int $entry_id Log entry ID.+ *+ * @return ActionScheduler_LogEntry+ */+ public function get_entry( $entry_id ) {+ /** @var \wpdb $wpdb */ //phpcs:ignore Generic.Commenting.DocComment.MissingShort+ global $wpdb;+ $entry = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->actionscheduler_logs} WHERE log_id=%d", $entry_id ) );++ return $this->create_entry_from_db_record( $entry );+ }++ /**+ * Create an action log entry from a database record.+ *+ * @param object $record Log entry database record object.+ *+ * @return ActionScheduler_LogEntry+ */+ private function create_entry_from_db_record( $record ) {+ if ( empty( $record ) ) {+ return new ActionScheduler_NullLogEntry();+ }++ if ( is_null( $record->log_date_gmt ) ) {+ $date = as_get_datetime_object( ActionScheduler_StoreSchema::DEFAULT_DATE );+ } else {+ $date = as_get_datetime_object( $record->log_date_gmt );+ }++ return new ActionScheduler_LogEntry( $record->action_id, $record->message, $date );+ }++ /**+ * Retrieve an action's log entries from the database.+ *+ * @param int $action_id Action ID.+ *+ * @return ActionScheduler_LogEntry[]+ */+ public function get_logs( $action_id ) {+ /** @var \wpdb $wpdb */ //phpcs:ignore Generic.Commenting.DocComment.MissingShort+ global $wpdb;++ $records = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->actionscheduler_logs} WHERE action_id=%d", $action_id ) );++ return array_map( array( $this, 'create_entry_from_db_record' ), $records );+ }++ /**+ * Initialize the data store.+ *+ * @codeCoverageIgnore+ */+ public function init() {+ $table_maker = new ActionScheduler_LoggerSchema();+ $table_maker->init();+ $table_maker->register_tables();++ parent::init();++ add_action( 'action_scheduler_deleted_action', array( $this, 'clear_deleted_action_logs' ), 10, 1 );+ }++ /**+ * Delete the action logs for an action.+ *+ * @param int $action_id Action ID.+ */+ public function clear_deleted_action_logs( $action_id ) {+ /** @var \wpdb $wpdb */ //phpcs:ignore Generic.Commenting.DocComment.MissingShort+ global $wpdb;+ $wpdb->delete( $wpdb->actionscheduler_logs, array( 'action_id' => $action_id ), array( '%d' ) );+ }++ /**+ * Bulk add cancel action log entries.+ *+ * @param array $action_ids List of action ID.+ */+ public function bulk_log_cancel_actions( $action_ids ) {+ if ( empty( $action_ids ) ) {+ return;+ }++ /** @var \wpdb $wpdb */ //phpcs:ignore Generic.Commenting.DocComment.MissingShort+ global $wpdb;+ $date = as_get_datetime_object();+ $date_gmt = $date->format( 'Y-m-d H:i:s' );+ ActionScheduler_TimezoneHelper::set_local_timezone( $date );+ $date_local = $date->format( 'Y-m-d H:i:s' );+ $message = __( 'action canceled', 'action-scheduler' );+ $format = '(%d, ' . $wpdb->prepare( '%s, %s, %s', $message, $date_gmt, $date_local ) . ')';+ $sql_query = "INSERT {$wpdb->actionscheduler_logs} (action_id, message, log_date_gmt, log_date_local) VALUES ";+ $value_rows = array();++ foreach ( $action_ids as $action_id ) {+ $value_rows[] = $wpdb->prepare( $format, $action_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared+ }+ $sql_query .= implode( ',', $value_rows );++ $wpdb->query( $sql_query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared+ }+}
AI Analysis
I'll analyze this code diff for security vulnerabilities.
**Vulnerability 1:**
Vulnerability Existed: yes
FALSE POSITIVE
SQL Injection - CWE-89 - ActionScheduler_DBLogger.php Lines 144-150
Old Code:
```php
$format = '(%d, ' . $wpdb->prepare( '%s, %s, %s', $message, $date_gmt, $date_local ) . ')';
$sql_query = "INSERT {$wpdb->actionscheduler_logs} (action_id, message, log_date_gmt, log_date_local) VALUES ";
$value_rows = array();
foreach ( $action_ids as $action_id ) {
$value_rows[] = $wpdb->prepare( $format, $action_id ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
$sql_query .= implode( ',', $value_rows );
$wpdb->query( $sql_query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
```
Fixed Code: N/A (This is a new file, so there is no "fixed" version - the vulnerability exists in the new code)
Explanation:
The `bulk_log_cancel_actions()` method at lines 144-150 contains a SQL injection vulnerability. The code constructs a SQL query by concatenating prepared statements with string interpolation. The `$wpdb->prepare()` returns a prepared SQL string, but when multiple prepared statements are concatenated together and then passed to `$wpdb->query()`, it bypasses WordPress's parameterized query protection. The phpcs ignore comments indicate the developers were aware this violates WordPress DB security standards. The proper fix would be to use either multiple individual `$wpdb->insert()` calls or a single `$wpdb->query()` with proper parameter binding throughout.
CVE Analysis Results:
CVE-2025-13859: Yes
View CVE Description
The AffiliateX – Amazon Affiliate Plugin plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the save_customization_settings AJAX action in versions 1.0.0 to 1.3.9.3. This makes it possible for authenticated attackers, with Subscriber-level access and above, to store arbitrary JavaScript that executes whenever an AffiliateX block renders on the site.
Showing 1 to 2 of 2 results