Commit 99b7baed01 for wordpress.org

commit 99b7baed01eab7faf6eefd79401d0fdaab6d0011
Author: westonruter <westonruter@git.wordpress.org>
Date:   Fri Sep 25 01:56:47 2026 +0000

    XML-RPC: Reject non-scalar login credentials.

    Previously, sending an array or struct as the username or password to any XML-RPC method requiring authentication caused a fatal error, since `wp_xmlrpc_server::login()` passed the credentials straight to `wp_authenticate()`, which calls `trim()` on them. Now `wp_xmlrpc_server::login()` returns a `400` fault when either credential is not a scalar. Other scalar values are still passed through for backward compatibility, since PHP coerces them to strings.

    Additionally, the documented types for `wp_xmlrpc_server::error()`, the `pre_upload_error` filter, and `WP_HTTP_IXR_Client::$error` are corrected, and `pingback()` now checks for an `IXR_Error` instance before reading the fault code. This resolves static analysis errors that surfaced with the `IXR_Error` types added in r63901. A test is also added for a pingback that the remote server reports as already registered.

    Developed in https://github.com/WordPress/wordpress-develop/pull/13692.
    Follow-up to r30179, r50954, r63901.

    Props josephscott, westonruter, anupkankale.
    See #66160, #65817.
    Fixes #66168.

    Built from https://develop.svn.wordpress.org/trunk@63927


    git-svn-id: http://core.svn.wordpress.org/trunk@63093 1a063a9b-81f0-0310-95a4-ce76da25c4cd

diff --git a/wp-includes/class-wp-http-ixr-client.php b/wp-includes/class-wp-http-ixr-client.php
index d4f7936cca..253497a7c8 100644
--- a/wp-includes/class-wp-http-ixr-client.php
+++ b/wp-includes/class-wp-http-ixr-client.php
@@ -9,7 +9,7 @@
 class WP_HTTP_IXR_Client extends IXR_Client {
 	public $scheme;
 	/**
-	 * @var IXR_Error
+	 * @var IXR_Error|null
 	 */
 	public $error;

diff --git a/wp-includes/class-wp-xmlrpc-server.php b/wp-includes/class-wp-xmlrpc-server.php
index 1a0a462622..9d4ee81cc6 100644
--- a/wp-includes/class-wp-xmlrpc-server.php
+++ b/wp-includes/class-wp-xmlrpc-server.php
@@ -287,6 +287,7 @@ class wp_xmlrpc_server extends IXR_Server {
 	 * Logs user in.
 	 *
 	 * @since 2.8.0
+	 * @since 7.2.0 Returns an error if the `$username` or `$password` argument is not a scalar.
 	 *
 	 * @param string $username User's username.
 	 * @param string $password User's password.
@@ -302,6 +303,16 @@ class wp_xmlrpc_server extends IXR_Server {
 			return false;
 		}

+		/*
+		 * Arrays and objects sent by the client would cause a fatal error in
+		 * wp_authenticate(). Other scalar types are tolerated because PHP
+		 * coerces them to strings, which preserves backward compatibility.
+		 */
+		if ( ! is_scalar( $username ) || ! is_scalar( $password ) ) {
+			$this->error = new IXR_Error( 400, __( 'The username and password arguments should be strings.' ) );
+			return false;
+		}
+
 		if ( $this->auth_failed ) {
 			$user = new WP_Error( 'login_prevented' );
 		} else {
@@ -381,8 +392,8 @@ class wp_xmlrpc_server extends IXR_Server {
 	 *
 	 * @since 5.7.3
 	 *
-	 * @param IXR_Error|string $error   Error code or an error object.
-	 * @param false            $message Error message. Optional.
+	 * @param IXR_Error|int $error   Error code or an error object.
+	 * @param string|false  $message Error message. Optional. Default false.
 	 */
 	public function error( $error, $message = false ) {
 		// Accepts either an error object or an error code and message
@@ -6621,7 +6632,8 @@ class wp_xmlrpc_server extends IXR_Server {
 		 *
 		 * @since 2.1.0
 		 *
-		 * @param bool $error Whether to pre-empt the media upload. Default false.
+		 * @param string|false $error Error message to return instead of uploading, or false to
+		 *                            allow the upload. Default false.
 		 */
 		$upload_err = apply_filters( 'pre_upload_error', false );
 		if ( $upload_err ) {
diff --git a/wp-includes/comment.php b/wp-includes/comment.php
index 03511ee4db..ae4b8efbbc 100644
--- a/wp-includes/comment.php
+++ b/wp-includes/comment.php
@@ -3625,7 +3625,7 @@ function pingback( $content, $post ) {
 			$status = $client->query( 'pingback.ping', $pagelinkedfrom, $pagelinkedto );

 			if ( $status // Ping registered.
-				|| ( isset( $client->error->code ) && 48 === $client->error->code ) // Already registered.
+				|| ( $client->error instanceof IXR_Error && 48 === $client->error->code ) // Already registered.
 			) {
 				add_ping( $post, $pagelinkedto );
 			}
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 72728a00e5..ff4a3aca86 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '7.2-alpha-63926';
+$wp_version = '7.2-alpha-63927';

 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.