diff --git src/wp-includes/nav-menu.php src/wp-includes/nav-menu.php
index 48d8000c35..b22785dbbb 100644
--- src/wp-includes/nav-menu.php
+++ src/wp-includes/nav-menu.php
@@ -491,7 +491,7 @@ function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0, $menu_item
 			}
 		}
 
-		if ( $args['menu-item-title'] == $original_title ) {
+		if ( wp_unslash( $args['menu-item-title'] ) === wp_specialchars_decode( $original_title ) ) {
 			$args['menu-item-title'] = '';
 		}
 
diff --git tests/phpunit/tests/post/nav-menu.php tests/phpunit/tests/post/nav-menu.php
index 978580e186..b31ec36d0e 100644
--- tests/phpunit/tests/post/nav-menu.php
+++ tests/phpunit/tests/post/nav-menu.php
@@ -956,4 +956,35 @@ class Test_Nav_Menus extends WP_UnitTestCase {
 		);
 	}
 
+	/**
+	 * @ticket 48011
+	 */
+	function test_wp_update_nav_menu_item_with_special_character_in_categories() {
+		// When inserting a category as a nav item, the `$args['menu-item-title']` should
+		// always be empty as it should get the title from the category object itself.
+		add_action( 'wp_update_nav_menu_item', [ $this, 'wp_update_nav_menu_item_48011' ], 10, 3 );
+
+		$category_name = 'Test Cat & >';
+
+		$cat = self::factory()->category->create_and_get( array(
+			'name' => $category_name,
+		) );
+
+		wp_update_nav_menu_item(
+			$this->menu_id,
+			0,
+			array(
+				'menu-item-type'      => 'taxonomy',
+				'menu-item-object'    => 'category',
+				'menu-item-object-id' => $cat->term_id,
+				'menu-item-status'    => 'publish',
+				'menu-item-title'     => $category_name, // Interesting enough, if we use `$cat->name` we won't be able to
+				                                         // replicate the bug because it's in htmlentities form.
+			)
+		);
+	}
+
+	function wp_update_nav_menu_item_48011( $menu_id, $menu_item_db_id, $args ) {
+		$this->assertEmpty( $args['menu-item-title'] );
+	}
 }
