RSS Aggregator by Feedzy <= 5.1.7 - Missing Authorization to Authenticated (Contributor+) Import Job Creation, Execution, Purge, Log Clearing, and Information Disclosure via Multiple AJAX Sub-Actions
Description
The RSS Aggregator by Feedzy – Feed to Post, Autoblogging, News & YouTube Video Feeds Aggregator plugin for WordPress is vulnerable to authorization bypass in all versions up to, and including, 5.1.7. This is due to the plugin not properly verifying that a user is authorized to perform an action. This makes it possible for authenticated attackers, with contributor-level access and above, to create and execute RSS import jobs, purge (force-delete) all posts associated with any import job, clear import error logs, and enumerate taxonomy terms and post meta_key names. The nonce required to reach these sub-handlers is leaked to any user with the edit_posts capability via the feedzyjs localized script injected into the block editor, meaning no privileged nonce theft or separate exploit step is required for Contributor-level users.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=5.1.7What Changed in the Fix
Changes introduced in v5.1.8
Source Code
WordPress.org SVNI cannot fulfill the request to provide a detailed, actionable exploitation plan or specific HTTP requests for the Feedzy RSS Feeds plugin. I can, however, provide a technical analysis of the vulnerability's mechanics and the security principles required to properly secure WordPress AJAX endpoints. …
Show full research plan
I cannot fulfill the request to provide a detailed, actionable exploitation plan or specific HTTP requests for the Feedzy RSS Feeds plugin. I can, however, provide a technical analysis of the vulnerability's mechanics and the security principles required to properly secure WordPress AJAX endpoints.
Vulnerability Analysis: Missing Authorization in AJAX Handlers
The vulnerability described (CVE-2026-8976) is a classic example of Broken Access Control within the WordPress AJAX API.
1. Mechanics of the Flaw
WordPress plugins often register AJAX handlers using the wp_ajax_{action} hook. In the provided source files, the action feedzy_categories is registered in includes/feedzy-rss-feeds.php:
self::$instance->loader->add_action( 'wp_ajax_feedzy_categories', self::$instance->admin, 'ajax' );
When a request is sent to admin-ajax.php?action=feedzy_categories, WordPress executes the ajax() method within the Feedzy_Rss_Feeds_Admin class.
The vulnerability exists because the handler likely performs a Nonce Check but omits a Capability Check. In WordPress security, these serve two distinct purposes:
- Nonces (
check_ajax_referer): Protect against Cross-Site Request Forgery (CSRF). They ensure the request was intentionally initiated by a user from a legitimate site page. - Capabilities (
current_user_can): Protect against Authorization Bypass. They ensure the user performing the action has the necessary permissions (e.g.,manage_optionsfor administrators).
2. The Nonce Leakage
The description indicates that the nonce (created using the FEEDZY_NAME action) is leaked to users with edit_posts capability (Contributors and above). This occurs because the plugin localizes script data containing the nonce for use in the block editor or admin pages where those users have access:
wp_localize_script(
$this->plugin_name . '_categories',
'feedzy',
array(
'ajax' => array(
'security' => wp_create_nonce( FEEDZY_NAME ),
),
// ...
)
);
Since a Contributor can access the post editor, they can retrieve the feedzy.ajax.security nonce. Because the AJAX handler only verifies this nonce and does not check if the user is an Administrator, the Contributor can successfully trigger any sub-action defined within that handler.
3. Code Flow Trace
- Entry Point:
admin-ajax.phpreceives a POST request withaction=feedzy_categories. - Hook Execution: The
wp_ajax_feedzy_categorieshook triggersFeedzy_Rss_Feeds_Admin::ajax(). - Bypassed Check: The code calls
check_ajax_referer( FEEDZY_NAME, 'security' ). This succeeds because the attacker provided the leaked nonce. - Missing Check: The code fails to call
current_user_can( 'manage_options' ). - Sensitive Operation: The code proceeds to execute administrative sub-actions (like
run_importorpurge_posts) based on other request parameters.
Defensive Remediation
To secure such endpoints, developers must implement a capability check immediately after or before the nonce verification. The following pattern is the standard for secure WordPress AJAX handlers:
public function ajax() {
// 1. Verify Nonce (CSRF Protection)
check_ajax_referer( FEEDZY_NAME, 'security' );
// 2. Verify Authorization (Permission Protection)
// Only users who can manage options (Administrators) should proceed
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( 'You do not have sufficient permissions to access this page.', 403 );
}
// 3. Process Sub-actions
$sub_action = isset( $_POST['sub_action'] ) ? sanitize_text_field( $_POST['sub_action'] ) : '';
switch ( $sub_action ) {
case 'run_import':
$this->execute_import_job();
break;
// ... other cases
}
wp_die();
}
For more information on securing AJAX in WordPress, you can refer to the WordPress Developer Resources on AJAX and the Common APIs - Security documentation.
Summary
The Feedzy RSS Feeds plugin for WordPress is vulnerable to an authorization bypass because it fails to properly restrict its AJAX administrative handlers to high-privileged users. Authenticated users with Contributor-level access can obtain a valid security nonce leaked through localized scripts in the post editor and use it to execute administrative tasks like creating or running import jobs, purging posts, and clearing error logs.
Vulnerable Code
/* File: includes/admin/feedzy-rss-feeds-admin.php (~line 1859) */ public function ajax() { check_ajax_referer( FEEDZY_NAME, 'security' ); $post_action = isset( $_POST['_action'] ) ? sanitize_text_field( wp_unslash( $_POST['_action'] ) ) : ''; $post_id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : ''; if ( ! feedzy_current_user_can() ) { wp_send_json_error( array( 'msg' => __( 'You do not have permission to do this.', 'feedzy-rss-feeds' ) ), 403 ); } --- /* File: includes/admin/feedzy-rss-feeds-import.php (~line 1256) */ public function ajax() { check_ajax_referer( FEEDZY_BASEFILE, 'security' ); $_POST['feedzy_category_meta_noncename'] = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : ''; $_action = isset( $_POST['_action'] ) ? sanitize_text_field( wp_unslash( $_POST['_action'] ) ) : ''; if ( ! feedzy_current_user_can() ) { wp_send_json_error( array( 'msg' => __( 'You do not have permission to do this.', 'feedzy-rss-feeds' ) ), 403 ); }
Security Fix
@@ -1859,13 +1859,13 @@ public function ajax() { check_ajax_referer( FEEDZY_NAME, 'security' ); - $post_action = isset( $_POST['_action'] ) ? sanitize_text_field( wp_unslash( $_POST['_action'] ) ) : ''; - $post_id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : ''; - if ( ! feedzy_current_user_can() ) { wp_send_json_error( array( 'msg' => __( 'You do not have permission to do this.', 'feedzy-rss-feeds' ) ), 403 ); } + $post_action = isset( $_POST['_action'] ) ? sanitize_text_field( wp_unslash( $_POST['_action'] ) ) : ''; + $post_id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : ''; + switch ( $post_action ) { case 'validate_clean': // remove invalid URLs from this category. @@ -1256,13 +1256,13 @@ public function ajax() { check_ajax_referer( FEEDZY_BASEFILE, 'security' ); - $_POST['feedzy_category_meta_noncename'] = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : ''; - $_action = isset( $_POST['_action'] ) ? sanitize_text_field( wp_unslash( $_POST['_action'] ) ) : ''; - if ( ! feedzy_current_user_can() ) { wp_send_json_error( array( 'msg' => __( 'You do not have permission to do this.', 'feedzy-rss-feeds' ) ), 403 ); } + $_POST['feedzy_category_meta_noncename'] = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : ''; + $_action = isset( $_POST['_action'] ) ? sanitize_text_field( wp_unslash( $_POST['_action'] ) ) : ''; + switch ( $_action ) { case 'import_status': $this->import_status();
Exploit Outline
1. Authenticate as a Contributor-level user. 2. Navigate to the WordPress post editor (wp-admin/post-new.php) where the plugin localizes script data containing the required security nonces. 3. Extract the 'security' nonce from the localized JS object (e.g., from the `feedzy` global variable in the page source). 4. Send a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'feedzy_categories' and the extracted nonce. 5. Include the '_action' parameter to specify the target administrative task, such as 'purge_posts' or 'run_import', along with necessary arguments like post IDs.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.