Opened 5 weeks ago
Last modified 3 weeks ago
#65048 assigned defect (bug)
wp_ajax_fetch_list(): Sanitize $_GET input before nonce construction
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Milestone: | Awaiting Review | Priority: | normal |
| Severity: | normal | Version: | 3.1 |
| Component: | Administration | Keywords: | has-patch needs-testing has-test-info |
| Focuses: | Cc: |
Description
In wp_ajax_fetch_list() (wp-admin/includes/ajax-actions.php), raw $_GET data is read without an existence check or sanitization before being used to construct the nonce action string and passed to _get_list_table().
Attachments (2)
Change History (7)
This ticket was mentioned in PR #11526 on WordPress/wordpress-develop by rajeshcpr.
5 weeks ago
#1
#2
@
3 weeks ago
- Severity changed from critical to normal
- Version changed from trunk to 3.1
If this is critical and it is a security fix, then it should not have been reported in Trac but rather on HackerOne. Please report the issue there if it is critical, otherwise, this seems to be a hardening for a hypothetical issue. (Do not discuss here if it is actually not hypothetical. Provide reproduction steps in HackerOne.)
#3
@
3 weeks ago
See also: Reporting Security Vulnerabilities
#4
@
3 weeks ago
Test Report for Ticket #65048
Environment
OS: Windows (XAMPP)
PHP: 8.2.x
WordPress: 7.1-alpha (trunk)
Testing Area: wp_ajax_fetch_list() in wp-admin/includes/ajax-actions.php
The Problem
The wp_ajax_fetch_list() function used raw data from $_GETlist_args? to construct the nonce action string and for list table initialization. This lacks proper sanitization and triggers PHP warnings in PHP 8.2+ when parameters are missing.
Test code: add log in wp-admin/admin-ajax.php before
do_action( 'admin_init' );
<?php if ( isset($_GET['action']) && 'fetch_list' === $_GET['action'] ) { $raw_class = $_GET['list_args']['class'] ?? 'N/A'; $clean_class = isset($_GET['list_args']['class']) ? sanitize_key($_GET['list_args']['class']) : ''; error_log( "--- Ticket #65048 Audit ---" ); error_log( "Action: fetch_list" ); error_log( "Raw Class: [" . $raw_class . "]" ); error_log( "Sanitized: [" . $clean_class . "]" ); error_log( "---------------------------" ); $list_class = $_GET['list_args']['class']; $screen_id = $_GET['list_args']['screen']['id']; error_log( "DEBUG 65048: Raw List Class = " . ($list_class ?? 'NULL') ); error_log( "DEBUG 65048: Raw Screen ID = " . ($screen_id ?? 'NULL') ); } /** This action is documented in wp-admin/admin.php */ do_action( 'admin_init' );
Test Results (Verification)
By intercepting the request at the AJAX entry point, the following results were recorded:
Test 1: Input Sanitization
Request
jQuery.get( ajaxurl, {
action: 'fetch_list',
list_args: {
class: 'My Custom Class!@#',
screen: { id: 'Screen ID 123' }
}
});
Log Output:
[23-Apr-2026 04:07:26 UTC] --- Ticket #65048 Audit --- [23-Apr-2026 04:07:26 UTC] Action: fetch_list [23-Apr-2026 04:07:26 UTC] Raw Class: [My Custom Class!@#] [23-Apr-2026 04:07:26 UTC] Sanitized: [mycustomclass] [23-Apr-2026 04:07:26 UTC] --------------------------- [23-Apr-2026 04:07:26 UTC] DEBUG 65048: Raw List Class = My Custom Class!@# [23-Apr-2026 04:07:26 UTC] DEBUG 65048: Raw Screen ID = Screen ID 123
Observation: sanitize_key() correctly stripped whitespace, uppercase letters, and special characters (!@#). This ensures the nonce action string "fetch-list-$list_class" is generated from safe, predictable input.
Test 2: PHP 8.2 Stability
Request: action=fetch_list (missing list_args)
jQuery.get( ajaxurl, {
action: 'fetch_list'
});
Log Output:
[23-Apr-2026 04:12:07 UTC] --- Ticket #65048 Audit --- [23-Apr-2026 04:12:07 UTC] Action: fetch_list [23-Apr-2026 04:12:07 UTC] Raw Class: [N/A] [23-Apr-2026 04:12:07 UTC] Sanitized: [] [23-Apr-2026 04:12:07 UTC] --------------------------- [23-Apr-2026 04:12:07 UTC] PHP Warning: Undefined array key "list_args" in C:\xampp\htdocs\wp-core\src\wp-admin\admin-ajax.php on line 54 [23-Apr-2026 04:12:07 UTC] PHP Warning: Trying to access array offset on value of type null in C:\xampp\htdocs\wp-core\src\wp-admin\admin-ajax.php on line 54 [23-Apr-2026 04:12:07 UTC] PHP Warning: Undefined array key "list_args" in C:\xampp\htdocs\wp-core\src\wp-admin\admin-ajax.php on line 55 [23-Apr-2026 04:12:07 UTC] PHP Warning: Trying to access array offset on value of type null in C:\xampp\htdocs\wp-core\src\wp-admin\admin-ajax.php on line 55 [23-Apr-2026 04:12:07 UTC] PHP Warning: Trying to access array offset on value of type null in C:\xampp\htdocs\wp-core\src\wp-admin\admin-ajax.php on line 55 [23-Apr-2026 04:12:07 UTC] DEBUG 65048: Raw List Class = NULL [23-Apr-2026 04:12:07 UTC] DEBUG 65048: Raw Screen ID = NULL
Pre-patch: Triggered PHP Warning: Undefined array key "list_args".
Post-patch: With isset() and ?? guards applied, no warnings were triggered. The values were safely defaulted to empty strings.
Summary of Improvements
Hardening: Prevents attackers from influencing the nonce action string via malicious character injection in the URL.
PHP 8.x Compatibility: Resolves array key existence issues, leading to a cleaner debug log and better system stability.
Verdict
The patch successfully sanitizes the required inputs and resolves modern PHP warnings. The implementation of sanitize_key() and isset() guards is correct and follows WordPress Core best practices.

Raw $_GETlist_args?class? and $_GETlist_args?screen?id? were used directly to build the nonce action string and passed to _get_list_table() without any sanitization or existence checks. An attacker controlling list_args[class] could influence the nonce key being verified, undermining the referer check. Apply sanitize_key() and isset() guards to both values before use, ensuring the nonce action string and _get_list_table() arguments are constructed from clean input.
Trac ticket: https://core.trac.wordpress.org/ticket/65048
Fixes #65048
## Use of AI Tools