Make WordPress Core

Opened 5 weeks ago

Last modified 2 hours ago

#44096 new defect (bug)

REST API: Taxonomy and term endpoints should use correct permission checks

Reported by: danielbachhuber Owned by:
Milestone: 4.9.7 Priority: normal
Severity: normal Version:
Component: Taxonomy Keywords: has-patch has-unit-tests
Focuses: rest-api Cc:


There are a couple of key changes we need to make:

  1. Switch GET /wp/v2/taxonomies?context=edit to reference $taxonomy->cap->assign_terms instead of $taxonomy->cap->manage_terms. Users who can assign terms need to be able to see all corresponding labeling.
  2. Permit users with $taxonomy->cap->assign_terms to create terms for non-hierarchical taxonomies (e.g. tags).

These suggestions are based on research for WordPress/gutenberg#5879, which I'll copy below for posterity.

Here's my table of UI-focused permission review.

The key difference between categories and tags: contributors and authors can create tags, but they can't create categories. This distinction applies more broadly to non-hierarchical vs. hierarchical taxonomies.

Fortunately, the only low-level permissions check is in wp_insert_post(). More specifically:

foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
	$taxonomy_obj = get_taxonomy( $taxonomy );
	// array = hierarchical, string = non-hierarchical.
	if ( is_array( $tags ) ) {
		$tags = array_filter( $tags );
	if ( current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
		wp_set_post_terms( $post_ID, $tags, $taxonomy );

After this logic, wp_set_post_terms() calls wp_set_object_terms() and neither has permissions checks. Because of how wp_set_object_terms() behaves, strings passed for a non-hierarchical taxonomy will be magically transformed into terms. wp_set_object_terms() always expects an array of integers (representing valid terms) for hierarchical taxonomies.

I say "fortunately" because core's existing implementation also means we don't have to enter the rabbit hole of developer-defined custom taxonomy UI. edit_post() blindly accepts and processes data included in tax_input, regardless of whether a developer implemented some bespoke UI for the taxonomy.

Given this information, we can assume:

  1. A user can set terms on a post if they have assign_terms for the taxonomy and can edit the post. This also means they can access all terms (including empty, non-public ones).
  2. A user can create new terms if they have assign_terms for a non-hierarchical taxonomy, or edit_terms for a hierarchical taxonomy.

However, now we run into WordPress/gutenberg#6361 because capabilities are evaluated at runtime.

Attachments (1)

44096.1.diff (7.9 KB) - added by danielbachhuber 5 weeks ago.

Download all attachments as: .zip

Change History (3)

#1 @desrosj
5 weeks ago

  • Milestone changed from 4.9.7 to 4.9.8

Moving all tickets in 4.9.7 to 4.9.8.

#2 @danielbachhuber
2 hours ago

  • Milestone changed from 4.9.8 to 4.9.7
Note: See TracTickets for help on using tickets.