Make WordPress Core

Changeset 63016


Ignore:
Timestamp:
08/05/2026 01:33:06 AM (6 weeks ago)
Author:
westonruter
Message:

Networks and Sites: Improve user autocomplete search term handling.

In wp_ajax_autocomplete_user(), unslash and sanitize the term request parameter before it is passed to get_users(). Unslashing fixes searching for an email address containing an apostrophe (valid per is_email()), which could previously never match because wp_magic_quotes() added a slash which wpdb::esc_like() then escaped as a literal. Note that the raw term was already safely handled in the user query, since WP_User_Query passes the search term through wpdb::prepare(), so this is a hardening and correctness fix rather than a security fix.

Additionally, a missing, non-string, or empty term now short-circuits with a 0 response instead of returning an empty array, avoiding a PHP warning and needless user queries. Asterisks are also trimmed from the term given that wildcards are appended to it; a term consisting only of asterisks previously resulted in an empty search which matched all users on the network.

Also introduce the Tests_Ajax_wpAjaxAutocompleteUser test class covering the Ajax action's search behavior, input handling, and capability checks.

Developed in https://github.com/WordPress/wordpress-develop/pull/11530.
Follow-up to r19897, r20279.

Props rajeshcp, wildworks, westonruter, liaison, gaurangsondagar, vgnavada, saadtajik.
Fixes #65051.

Location:
trunk
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/ajax-actions.php

    r62956 r63016  
    286286 *
    287287 * @since 3.4.0
     288 * @since 7.1.0 The search term is now sanitized, and a missing, non-string,
     289 *              or empty term results in a `0` response instead of an empty array.
     290 *
     291 * @return never
    288292 */
    289293function wp_ajax_autocomplete_user() {
     
    298302
    299303        $return = array();
     304
     305        // Obtain the search term, and short-circuit missing/invalid search term.
     306        if ( ! isset( $_REQUEST['term'] ) || ! is_string( $_REQUEST['term'] ) ) {
     307                wp_die( 0 );
     308        }
     309        /*
     310         * Asterisks are trimmed since wildcards are appended below. Without this, a
     311         * term consisting only of asterisks would result in an empty search that
     312         * matches all users.
     313         */
     314        $term = trim( sanitize_text_field( wp_unslash( $_REQUEST['term'] ) ), '*' );
     315        if ( '' === $term ) {
     316                wp_die( 0 );
     317        }
    300318
    301319        /*
     
    343361                array(
    344362                        'blog_id'        => false,
    345                         'search'         => '*' . $_REQUEST['term'] . '*',
     363                        'search'         => '*' . $term . '*',
    346364                        'include'        => $include_blog_users,
    347365                        'exclude'        => $exclude_blog_users,
Note: See TracChangeset for help on using the changeset viewer.