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.
*/