Commit 480fe0bead for wordpress.org

commit 480fe0bead018cce24e6e8c55d67376144444b8a
Author: johnbillion <johnbillion@git.wordpress.org>
Date:   Mon Nov 9 23:32:48 2026 +0000

    Application Passwords: Pass unslashed data to hooks.

    The name of an application password appeared with backslashes in the "Application Password Created" email, so a name such as `Bob's App` showed as `Bob\'s App`. This happened because `WP_Application_Passwords::create_new_application_password()` and `::update_application_password()` expect slashed data and have passed it to their actions unchanged since 5.6.0. Both methods now unslash their input.

    Developed in: https://github.com/WordPress/wordpress-develop/pull/15608

    Follow-up to [63582], [64253], [65091].

    Props peterwilsoncc, jorbin, audrasjb, ssebuwufumoses.
    Fixes #63927.

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


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

diff --git a/wp-includes/class-wp-application-passwords.php b/wp-includes/class-wp-application-passwords.php
index 6e84e0a2b2..a7a952e66d 100644
--- a/wp-includes/class-wp-application-passwords.php
+++ b/wp-includes/class-wp-application-passwords.php
@@ -61,10 +61,11 @@ class WP_Application_Passwords {
 	 * @since 5.6.0
 	 * @since 5.7.0 Returns WP_Error if application name already exists.
 	 * @since 6.8.0 The hashed password value now uses wp_fast_hash() instead of phpass.
+	 * @since 7.2.0 The returned application password details are unslashed.
 	 *
 	 * @param int   $user_id  User ID.
 	 * @param array $args     {
-	 *     Arguments used to create the application password.
+	 *     Arguments used to create the application password. Expected to be slashed.
 	 *
 	 *     @type string $name   The name of the application password.
 	 *     @type string $app_id A UUID provided by the application to uniquely identify it.
@@ -87,6 +88,8 @@ class WP_Application_Passwords {
 	 * }
 	 */
 	public static function create_new_application_password( $user_id, $args = array() ) {
+		$args = wp_unslash( $args );
+
 		if ( ! empty( $args['name'] ) ) {
 			$args['name'] = sanitize_text_field( $args['name'] );
 		}
@@ -126,6 +129,7 @@ class WP_Application_Passwords {
 		 *
 		 * @since 5.6.0
 		 * @since 6.8.0 The hashed password value now uses wp_fast_hash() instead of phpass.
+		 * @since 7.2.0 The values in `$new_item` and `$args` are unslashed.
 		 *
 		 * @param int    $user_id      The user ID.
 		 * @param array  $new_item     {
@@ -256,7 +260,7 @@ class WP_Application_Passwords {
 	 * @param int    $user_id User ID.
 	 * @param string $uuid    The password's UUID.
 	 * @param array  $update  {
-	 *     Information about the application password to update.
+	 *     Information about the application password to update. Expected to be slashed.
 	 *
 	 *     @type string      $uuid      The unique identifier for the application password.
 	 *     @type string      $app_id    A UUID provided by the application to uniquely identify it.
@@ -269,6 +273,7 @@ class WP_Application_Passwords {
 	 * @return true|WP_Error True if successful, otherwise a WP_Error instance is returned on error.
 	 */
 	public static function update_application_password( $user_id, $uuid, $update = array() ) {
+		$update    = wp_unslash( $update );
 		$passwords = static::get_user_application_passwords( $user_id );

 		foreach ( $passwords as &$item ) {
@@ -301,6 +306,7 @@ class WP_Application_Passwords {
 			 * @since 5.6.0
 			 * @since 6.8.0 The password is now hashed using wp_fast_hash() instead of phpass.
 			 *              Existing passwords may still be hashed using phpass.
+			 * @since 7.2.0 The values in `$item` and `$update` are unslashed.
 			 *
 			 * @param int   $user_id The user ID.
 			 * @param array $item    {
@@ -433,10 +439,11 @@ class WP_Application_Passwords {
 	 * Sets a user's application passwords.
 	 *
 	 * @since 5.6.0
+	 * @since 7.2.0 The passwords are slashed before saving, so values containing backslashes are stored intact.
 	 *
 	 * @param int   $user_id   User ID.
 	 * @param array $passwords {
-	 *     The list of application passwords.
+	 *     The list of unslashed application passwords.
 	 *
 	 *     @type array ...$0 {
 	 *         @type string      $uuid      The unique identifier for the application password.
@@ -453,7 +460,8 @@ class WP_Application_Passwords {
 	 *                  is the same as the one that is already in the database.
 	 */
 	protected static function set_user_application_passwords( $user_id, $passwords ) {
-		return update_user_meta( $user_id, static::USERMETA_KEY_APPLICATION_PASSWORDS, $passwords );
+		// The metadata API unslashes its input, so slash it to store the values as given.
+		return update_user_meta( $user_id, static::USERMETA_KEY_APPLICATION_PASSWORDS, wp_slash( $passwords ) );
 	}

 	/**
diff --git a/wp-includes/functions.php b/wp-includes/functions.php
index 2f5f56d8bd..16911734cf 100644
--- a/wp-includes/functions.php
+++ b/wp-includes/functions.php
@@ -9585,6 +9585,8 @@ function wp_verify_fast_hash(
 /**
  * Sends an email to the user when a new application password is created.
  *
+ * Hooked to the {@see 'wp_create_application_password'} action.
+ *
  * @since 7.2.0
  *
  * @param int   $user_id  The user ID.
@@ -9614,9 +9616,19 @@ function wp_application_password_created_notification( $user_id, $new_item ) {
 	 *
 	 * @since 7.2.0
 	 *
-	 * @param bool    $send  Whether to send the email notification.
-	 * @param WP_User $user  The user object.
-	 * @param array   $new_item The application password details.
+	 * @param bool    $send     Whether to send the email notification.
+	 * @param WP_User $user     The user object.
+	 * @param array   $new_item {
+	 *     The details about the created password.
+	 *
+	 *     @type string $uuid      The unique identifier for the application password.
+	 *     @type string $app_id    A UUID provided by the application to uniquely identify it.
+	 *     @type string $name      The name of the application password.
+	 *     @type string $password  A one-way hash of the password.
+	 *     @type int    $created   Unix timestamp of when the password was created.
+	 *     @type null   $last_used Null.
+	 *     @type null   $last_ip   Null.
+	 * }
 	 */
 	$send = apply_filters( 'wp_send_application_password_created_email', $send, $user, $new_item );

@@ -9677,7 +9689,17 @@ All at ###SITENAME###
 	 *     @type string $headers Headers.
 	 * }
 	 * @param WP_User $user     The user object.
-	 * @param array   $new_item The application password details.
+	 * @param array   $new_item {
+	 *     The details about the created password.
+	 *
+	 *     @type string $uuid      The unique identifier for the application password.
+	 *     @type string $app_id    A UUID provided by the application to uniquely identify it.
+	 *     @type string $name      The name of the application password.
+	 *     @type string $password  A one-way hash of the password.
+	 *     @type int    $created   Unix timestamp of when the password was created.
+	 *     @type null   $last_used Null.
+	 *     @type null   $last_ip   Null.
+	 * }
 	 */
 	$email = apply_filters( 'wp_application_password_created_email', $email, $user, $new_item );

diff --git a/wp-includes/version.php b/wp-includes/version.php
index bf2fa80691..ed1492cee2 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '7.2-beta4-65360';
+$wp_version = '7.2-beta4-65361';

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