[wp-trac] [WordPress Trac] #65035: Abilities: Strip internal schema keywords from abilities REST responses

WordPress Trac noreply at wordpress.org
Tue Apr 7 13:22:52 UTC 2026


#65035: Abilities: Strip internal schema keywords from abilities REST responses
------------------------------+--------------------------------------
 Reporter:  jorgefilipecosta  |      Owner:  (none)
     Type:  defect (bug)      |     Status:  new
 Priority:  normal            |  Milestone:  7.0
Component:  AI                |    Version:
 Severity:  normal            |   Keywords:  has-patch has-unit-tests
  Focuses:                    |
------------------------------+--------------------------------------
 The Abilities REST API endpoint ({{{/wp/v2/abilities}}}) returns
 {{{input_schema}}} and {{{output_schema}}} that may contain WordPress-
 internal properties like {{{sanitize_callback}}}, {{{validate_callback}}},
 and {{{arg_options}}}. These are not valid JSON Schema keywords and cause
 client-side JSON Schema validators to reject the schemas.

 For example, a plugin registering an ability with {{{register_ability()}}}
 that includes {{{sanitize_callback}}} or {{{arg_options}}} in its schema
 arguments will surface those internal keywords in the REST response.
 Clients consuming the API (such as Gutenberg's AI tools integration)
 cannot validate these schemas without error.

 == Proposed Fix ==

 Add a recursive {{{strip_internal_schema_keywords()}}} method to
 {{{WP_REST_Abilities_V1_List_Controller}}} that removes the three internal
 keywords from schemas before they appear in REST responses.

 The method uses a '''denylist''' approach ({{{array_diff_key()}}} against
 a class constant {{{INTERNAL_SCHEMA_KEYWORDS}}}) rather than the
 '''allowlist''' approach ({{{rest_get_allowed_schema_keywords()}}} +
 {{{array_intersect_key()}}}) used in
 {{{WP_REST_Server::get_data_for_route()}}}. The denylist is the correct
 choice here because {{{rest_get_allowed_schema_keywords()}}} is missing
 valid JSON Schema keywords ({{{allOf}}}, {{{not}}}, {{{definitions}}},
 {{{dependencies}}}, {{{additionalItems}}}) that would be silently stripped
 with the allowlist approach.

 The recursive method traverses all JSON Schema sub-schema locations:
  * {{{properties}}}, {{{patternProperties}}}, {{{definitions}}},
 {{{dependencies}}} (map-of-schemas)
  * {{{not}}}, {{{additionalProperties}}}, {{{additionalItems}}} (single
 sub-schema)
  * {{{items}}} (single schema or tuple array)
  * {{{anyOf}}}, {{{oneOf}}}, {{{allOf}}} (array-of-schemas)

 Property-dependency arrays (numeric arrays in {{{dependencies}}}) are
 correctly skipped.

 The stripping is applied to both {{{input_schema}}} and
 {{{output_schema}}} in {{{prepare_item_for_response()}}}.

 == Test Coverage ==

  * Verifies internal keywords are stripped from top-level and nested
 properties in both {{{input_schema}}} and {{{output_schema}}}
  * Verifies internal keywords are stripped from all sub-schema locations
 ({{{anyOf}}}, {{{oneOf}}}, {{{allOf}}}, {{{not}}},
 {{{patternProperties}}}, {{{definitions}}}, {{{dependencies}}},
 {{{additionalProperties}}}, {{{additionalItems}}}, tuple-style
 {{{items}}})
  * Verifies valid JSON Schema keywords are preserved
  * Verifies property-dependency arrays pass through unchanged

 == Related ==

  * PR: [https://github.com/WordPress/wordpress-develop/pull/11451
 wordpress-develop#11451]
  * Broader schema compilation tracking: #64955

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/65035>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list