Commit d44340c26e8 for woocommerce
commit d44340c26e8aad9fddcf0629cbebddd2ffec303d
Author: Luis Felipe Zaguini <26530524+zaguiini@users.noreply.github.com>
Date: Mon Oct 19 08:19:40 2026 -0300
Refuse an extension query filter value that fails its schema (#69960)
* Refuse a query filter value that fails its schema, and a query filter on order items
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Drop the order_item check from register_query_filter()
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/fix-extensible-abilities-query-filter-checks b/plugins/woocommerce/changelog/fix-extensible-abilities-query-filter-checks
new file mode 100644
index 00000000000..ad05a638ed7
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-extensible-abilities-query-filter-checks
@@ -0,0 +1,3 @@
+Significance: patch
+Type: fix
+Comment: Refuse a query filter value that fails its schema in the unreleased extensible abilities feature.
diff --git a/plugins/woocommerce/src/Abilities/ExtensibleAbilities.php b/plugins/woocommerce/src/Abilities/ExtensibleAbilities.php
index 9be9ff482ad..f89a3e5a6f1 100644
--- a/plugins/woocommerce/src/Abilities/ExtensibleAbilities.php
+++ b/plugins/woocommerce/src/Abilities/ExtensibleAbilities.php
@@ -352,7 +352,7 @@ class ExtensibleAbilities {
*
* @param string $resource_name Resource.
* @param array<string, mixed> $input Ability input.
- * @return array<string, array>|\WP_Error The error of a filter that refused its value or failed.
+ * @return array<string, array>|\WP_Error The error of a value that fails its schema, or of a filter that refused its value or failed.
*/
public static function get_query_args( string $resource_name, array $input ) {
$query_args = array();
@@ -369,6 +369,10 @@ class ExtensibleAbilities {
}
$value = rest_sanitize_value_from_schema( $input['filters']['extensions'][ $namespace ][ $filter ], $args['schema'], $filter );
+ if ( is_wp_error( $value ) ) {
+ $value->add_data( array( 'status' => 400 ) );
+ return $value;
+ }
try {
$clauses = call_user_func( $args['callback'], $value );
} catch ( \Throwable $e ) {
diff --git a/plugins/woocommerce/tests/php/src/Internal/AbilitiesApi/ExtensibleAbilitiesTest.php b/plugins/woocommerce/tests/php/src/Internal/AbilitiesApi/ExtensibleAbilitiesTest.php
index bb3fe9e63fc..fe0afac6f76 100644
--- a/plugins/woocommerce/tests/php/src/Internal/AbilitiesApi/ExtensibleAbilitiesTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/AbilitiesApi/ExtensibleAbilitiesTest.php
@@ -758,6 +758,40 @@ class ExtensibleAbilitiesTest extends \WC_REST_Unit_Test_Case {
$this->assertSame( array( 'has_code', 'category' ), array_keys( $schema['properties']['filters']['properties']['extensions']['properties']['test-ext']['properties'] ) );
}
+ /**
+ * @testdox Should return a 400 error and not run the filter when a value that skipped validation fails its schema.
+ */
+ public function test_a_filter_value_that_fails_its_schema_is_refused(): void {
+ $called = false;
+ $register = static function () use ( &$called ) {
+ ExtensibleAbilities::register_query_filter(
+ array(
+ 'resource' => 'order',
+ 'namespace' => 'test-ext',
+ 'filter' => 'tags',
+ 'schema' => array(
+ 'type' => 'array',
+ 'items' => array( 'type' => 'string' ),
+ 'uniqueItems' => true,
+ ),
+ 'callback' => static function () use ( &$called ) {
+ $called = true;
+ return array();
+ },
+ )
+ );
+ };
+ add_action( 'woocommerce_extensible_abilities_init', $register );
+ $this->get_ability( 'woocommerce/orders-query' );
+ remove_action( 'woocommerce_extensible_abilities_init', $register );
+
+ $result = ExtensibleAbilities::get_query_args( 'order', array( 'filters' => array( 'extensions' => array( 'test-ext' => array( 'tags' => array( 'gift', 'gift' ) ) ) ) ) );
+
+ $this->assertWPError( $result );
+ $this->assertSame( 400, $result->get_error_data()['status'] );
+ $this->assertFalse( $called );
+ }
+
/**
* @testdox Should refuse a filter that is registered after the init action.
*/