Commit a3da8b1a795 for woocommerce

commit a3da8b1a795de34f5051a7019a6f18c5aaf12a3c
Author: Lucio Giannotta <lucio.giannotta@a8c.com>
Date:   Thu Nov 5 14:04:32 2026 -0500

    Keep view-order titles consistent with account access (#70604)

diff --git a/plugins/woocommerce/changelog/fix-view-order-title-permission b/plugins/woocommerce/changelog/fix-view-order-title-permission
new file mode 100644
index 00000000000..c3d70f6d820
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-view-order-title-permission
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Hide order numbers from account page titles when visitors cannot view the order.
diff --git a/plugins/woocommerce/includes/class-wc-query.php b/plugins/woocommerce/includes/class-wc-query.php
index 80e06da07f0..49abeac042b 100644
--- a/plugins/woocommerce/includes/class-wc-query.php
+++ b/plugins/woocommerce/includes/class-wc-query.php
@@ -138,8 +138,12 @@ class WC_Query {
 				break;
 			case 'view-order':
 				$order = wc_get_order( $wp->query_vars['view-order'] );
-				/* translators: %s: order number */
-				$title = ( $order ) ? sprintf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ) : '';
+				$title = '';
+				// Guest orders can pass the capability check for logged-out visitors because both use user ID 0.
+				if ( $order && is_user_logged_in() && current_user_can( 'view_order', $order->get_id() ) ) {
+					/* translators: %s: order number */
+					$title = sprintf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() );
+				}
 				break;
 			case 'downloads':
 				$title = __( 'Downloads', 'woocommerce' );
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-query-test.php b/plugins/woocommerce/tests/php/includes/class-wc-query-test.php
index bf61bab8d35..29d3d866ffb 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-query-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-query-test.php
@@ -7,6 +7,50 @@ declare( strict_types = 1 );
  */
 class WC_Query_Test extends \WC_Unit_Test_Case {

+	/**
+	 * @testdox View order titles disclose the order number only to customers who can view the order.
+	 * @testWith ["owner", true, "Order #CUSTOM-123"]
+	 *           ["other_customer", true, ""]
+	 *           ["logged_out", true, ""]
+	 *           ["owner", false, ""]
+	 *           ["logged_out", true, "", true]
+	 *
+	 * @param string $viewer         The customer viewing the endpoint.
+	 * @param bool   $order_exists   Whether the requested order exists.
+	 * @param string $expected_title The expected endpoint title.
+	 * @param bool   $guest_order    Whether the order belongs to a guest.
+	 */
+	public function test_get_view_order_endpoint_title( string $viewer, bool $order_exists, string $expected_title, bool $guest_order = false ): void {
+		$owner_id = self::factory()->user->create( array( 'role' => 'customer' ) );
+		$order_id = PHP_INT_MAX;
+
+		if ( $order_exists ) {
+			$order = new WC_Order();
+			$order->set_customer_id( $guest_order ? 0 : $owner_id );
+			$order_id = $order->save();
+		}
+
+		$user_id = $owner_id;
+		if ( 'other_customer' === $viewer ) {
+			$user_id = self::factory()->user->create( array( 'role' => 'customer' ) );
+		} elseif ( 'logged_out' === $viewer ) {
+			$user_id = 0;
+		}
+		wp_set_current_user( $user_id );
+
+		add_filter(
+			'woocommerce_order_number',
+			static function () {
+				return 'CUSTOM-123';
+			}
+		);
+
+		$this->go_to( '/?view-order=' . $order_id );
+		$sut = new WC_Query();
+
+		$this->assertSame( $expected_title, $sut->get_endpoint_title( 'view-order' ), 'Only an authorized customer should see the order number in the endpoint title.' );
+	}
+
 	/**
 	 * @testdox 'price_filter_post_clauses' generates the proper 'where' clause when there are 'max_price' and 'min_price' arguments in the query.
 	 */