CVE-2017-1001000: Insufficient Information (NVD-CWE-noinfo)
value: The register_routes function in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php in the REST API in WordPress 4.7.x before 4.7.2 does not require an integer identifier, which allows remote attackers to modify arbitrary pages via a request for wp-json/wp/v2/posts followed by a numeric value and a non-numeric value, as demonstrated by the wp-json/wp/v2/posts/123?id=123helloworld URI.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 7.5
Published: 2017-04-03T01:59Z
Repository: https://github.com/WordPress/WordPress
Language: PHP
Files changed: wp-includes/rest-api.php, wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php, wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php, wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php, wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php, wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php, wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php, wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php, wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php, wp-includes/version.php
Commit date: 2017-01-26 13:39:41 +0000
Commit message: REST API: Unify object access handling for simplicity.

Rather than repeating ourselves, unifying the access into a single method keeps everything tidy. While we're at it, add in additional schema handling for common parameters.

See #38792.
Built from https://develop.svn.wordpress.org/trunk@39954


git-svn-id: http://core.svn.wordpress.org/trunk@39891 1a063a9b-81f0-0310-95a4-ce76da25c4cd

Diff: diff --git a/wp-includes/rest-api.php b/wp-includes/rest-api.php
index 980f4c72a3..4f9e7e607f 100644
--- a/wp-includes/rest-api.php
+++ b/wp-includes/rest-api.php
@@ -44,10 +44,17 @@ function register_rest_route( $namespace, $route, $args = array(), $override = f
 	} else if ( empty( $route ) ) {
 		_doing_it_wrong( 'register_rest_route', __( 'Route must be specified.' ), '4.4.0' );
 		return false;
 	}
 
+	if ( isset( $args['args'] ) ) {
+		$common_args = $args['args'];
+		unset( $args['args'] );
+	} else {
+		$common_args = array();
+	}
+
 	if ( isset( $args['callback'] ) ) {
 		// Upgrade a single set to multiple.
 		$args = array( $args );
 	}
 
@@ -55,16 +62,17 @@ function register_rest_route( $namespace, $route, $args = array(), $override = f
 		'methods'         => 'GET',
 		'callback'        => null,
 		'args'            => array(),
 	);
 	foreach ( $args as $key => &$arg_group ) {
-		if ( ! is_numeric( $arg_group ) ) {
+		if ( ! is_numeric( $key ) ) {
 			// Route option, skip here.
 			continue;
 		}
 
 		$arg_group = array_merge( $defaults, $arg_group );
+		$arg_group['args'] = array_merge( $common_args, $arg_group['args'] );
 	}
 
 	$full_route = '/' . trim( $namespace, '/' ) . '/' . trim( $route, '/' );
 	$wp_rest_server->register_route( $namespace, $full_route, $args, $override );
 	return true;
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
index d7a34f3301..117529d19c 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
@@ -61,10 +61,16 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
 			),
 			'schema' => array( $this, 'get_public_item_schema' ),
 		) );
 
 		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
+			'args' => array(
+				'id' => array(
+					'description' => __( 'Unique identifier for the object.' ),
+					'type'        => 'integer',
+				),
+			),
 			array(
 				'methods'  => WP_REST_Server::READABLE,
 				'callback' => array( $this, 'get_item' ),
 				'permission_callback' => array( $this, 'get_item_permissions_check' ),
 				'args'     => array(
@@ -297,26 +303,53 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
 		}
 
 		return $response;
 	}
 
+	/**
+	 * Get the comment, if the ID is valid.
+	 *
+	 * @since 4.7.2
+	 *
+	 * @param int $id Supplied ID.
+	 * @return WP_Comment|WP_Error Comment object if ID is valid, WP_Error otherwise.
+	 */
+	protected function get_comment( $id ) {
+		$error = new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
+		if ( (int) $id <= 0 ) {
+			return $error;
+		}
+
+		$id = (int) $id;
+		$comment = get_comment( $id );
+		if ( empty( $comment ) ) {
+			return $error;
+		}
+
+		if ( ! empty( $comment->comment_post_ID ) ) {
+			$post = get_post( (int) $comment->comment_post_ID );
+			if ( empty( $post ) ) {
+				return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
+			}
+		}
+
+		return $comment;
+	}
+
 	/**
 	 * Checks if a given request has access to read the comment.
 	 *
 	 * @since 4.7.0
 	 * @access public
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_Error|bool True if the request has read access for the item, error object otherwise.
 	 */
 	public function get_item_permissions_check( $request ) {
-		$id = (int) $request['id'];
-
-		$comment = get_comment( $id );
-
-		if ( ! $comment ) {
-			return true;
+		$comment = $this->get_comment( $request['id'] );
+		if ( is_wp_error( $comment ) ) {
+			return $comment;
 		}
 
 		if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
 			return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit comments.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
@@ -342,22 +375,13 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
 	 */
 	public function get_item( $request ) {
-		$id = (int) $request['id'];
-
-		$comment = get_comment( $id );
-		if ( empty( $comment ) ) {
-			return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
-		}
-
-		if ( ! empty( $comment->comment_post_ID ) ) {
-			$post = get_post( $comment->comment_post_ID );
-			if ( empty( $post ) ) {
-				return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
-			}
+		$comment = $this->get_comment( $request['id'] );
+		if ( is_wp_error( $comment ) ) {
+			return $comment;
 		}
 
 		$data = $this->prepare_item_for_response( $comment, $request );
 		$response = rest_ensure_response( $data );
 
@@ -628,16 +652,16 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_Error|bool True if the request has access to update the item, error object otherwise.
 	 */
 	public function update_item_permissions_check( $request ) {
+		$comment = $this->get_comment( $request['id'] );
+		if ( is_wp_error( $comment ) ) {
+			return $comment;
+		}
 
-		$id = (int) $request['id'];
-
-		$comment = get_comment( $id );
-
-		if ( $comment && ! $this->check_edit_permission( $comment ) ) {
+		if ( ! $this->check_edit_permission( $comment ) ) {
 			return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this comment.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
 
 		return true;
 	}
@@ -650,18 +674,17 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
 	 */
 	public function update_item( $request ) {
-		$id = (int) $request['id'];
-
-		$comment = get_comment( $id );
-
-		if ( empty( $comment ) ) {
-			return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
+		$comment = $this->get_comment( $request['id'] );
+		if ( is_wp_error( $comment ) ) {
+			return $comment;
 		}
 
+		$id = $comment->comment_ID;
+
 		if ( isset( $request['type'] ) && get_comment_type( $id ) !== $request['type'] ) {
 			return new WP_Error( 'rest_comment_invalid_type', __( 'Sorry, you are not allowed to change the comment type.' ), array( 'status' => 404 ) );
 		}
 
 		$prepared_args = $this->prepare_item_for_database( $request );
@@ -748,15 +771,13 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_Error|bool True if the request has access to delete the item, error object otherwise.
 	 */
 	public function delete_item_permissions_check( $request ) {
-		$id      = (int) $request['id'];
-		$comment = get_comment( $id );
-
-		if ( ! $comment ) {
-			return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
+		$comment = $this->get_comment( $request['id'] );
+		if ( is_wp_error( $comment ) ) {
+			return $comment;
 		}
 
 		if ( ! $this->check_edit_permission( $comment ) ) {
 			return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this comment.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
@@ -771,19 +792,17 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
 	 */
 	public function delete_item( $request ) {
-		$id    = (int) $request['id'];
-		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
-
-		$comment = get_comment( $id );
-
-		if ( empty( $comment ) ) {
-			return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
+		$comment = $this->get_comment( $request['id'] );
+		if ( is_wp_error( $comment ) ) {
+			return $comment;
 		}
 
+		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
+
 		/**
 		 * Filters whether a comment can be trashed.
 		 *
 		 * Return false to disable trash support for the post.
 		 *
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php
index 0ec4bcd1a1..59575d566c 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-post-statuses-controller.php
@@ -46,10 +46,16 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
 			),
 			'schema' => array( $this, 'get_public_item_schema' ),
 		) );
 
 		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<status>[\w-]+)', array(
+			'args' => array(
+				'status' => array(
+					'description' => __( 'An alphanumeric identifier for the status.' ),
+					'type'        => 'string',
+				),
+			),
 			array(
 				'methods'             => WP_REST_Server::READABLE,
 				'callback'            => array( $this, 'get_item' ),
 				'permission_callback' => array( $this, 'get_item_permissions_check' ),
 				'args'                => array(
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php
index 4da4b52578..69d221be75 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php
@@ -46,10 +46,16 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
 			),
 			'schema' => array( $this, 'get_public_item_schema' ),
 		) );
 
 		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<type>[\w-]+)', array(
+			'args' => array(
+				'type' => array(
+					'description' => __( 'An alphanumeric identifier for the post type.' ),
+					'type'        => 'string',
+				),
+			),
 			array(
 				'methods'  => WP_REST_Server::READABLE,
 				'callback' => array( $this, 'get_item' ),
 				'args'     => array(
 					'context' => $this->get_context_param( array( 'default' => 'view' ) ),
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
index ef34f626e4..c33b8d1a70 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
@@ -86,10 +86,16 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 				'description' => __( 'The password for the post if it is password protected.' ),
 				'type'        => 'string',
 			);
 		}
 		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
+			'args' => array(
+				'id' => array(
+					'description' => __( 'Unique identifier for the object.' ),
+					'type'        => 'integer',
+				),
+			),
 			array(
 				'methods'             => WP_REST_Server::READABLE,
 				'callback'            => array( $this, 'get_item' ),
 				'permission_callback' => array( $this, 'get_item_permissions_check' ),
 				'args'                => $get_item_args,
@@ -347,22 +353,46 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 		}
 
 		return $response;
 	}
 
+	/**
+	 * Get the post, if the ID is valid.
+	 *
+	 * @since 4.7.2
+	 *
+	 * @param int $id Supplied ID.
+	 * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise.
+	 */
+	protected function get_post( $id ) {
+		$error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
+		if ( (int) $id <= 0 ) {
+			return $error;
+		}
+
+		$post = get_post( (int) $id );
+		if ( empty( $post ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
+			return $error;
+		}
+
+		return $post;
+	}
+
 	/**
 	 * Checks if a given request has access to read a post.
 	 *
 	 * @since 4.7.0
 	 * @access public
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise.
 	 */
 	public function get_item_permissions_check( $request ) {
-
-		$post = get_post( (int) $request['id'] );
+		$post = $this->get_post( $request['id'] );
+		if ( is_wp_error( $post ) ) {
+			return $post;
+		}
 
 		if ( 'edit' === $request['context'] && $post && ! $this->check_update_permission( $post ) ) {
 			return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this post.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
 
@@ -426,22 +456,20 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function get_item( $request ) {
-		$id   = (int) $request['id'];
-		$post = get_post( $id );
-
-		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
-			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
+		$post = $this->get_post( $request['id'] );
+		if ( is_wp_error( $post ) ) {
+			return $post;
 		}
 
 		$data     = $this->prepare_item_for_response( $post, $request );
 		$response = rest_ensure_response( $data );
 
 		if ( is_post_type_viewable( get_post_type_object( $post->post_type ) ) ) {
-			$response->link_header( 'alternate',  get_permalink( $id ), array( 'type' => 'text/html' ) );
+			$response->link_header( 'alternate',  get_permalink( $post->ID ), array( 'type' => 'text/html' ) );
 		}
 
 		return $response;
 	}
 
@@ -453,10 +481,13 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise.
 	 */
 	public function create_item_permissions_check( $request ) {
+		if ( ! empty( $request['id'] ) ) {
+			return new WP_Error( 'rest_post_exists', __( 'Cannot create existing post.' ), array( 'status' => 400 ) );
+		}
 
 		$post_type = get_post_type_object( $this->post_type );
 
 		if ( ! empty( $request['author'] ) && get_current_user_id() !== $request['author'] && ! current_user_can( $post_type->cap->edit_others_posts ) ) {
 			return new WP_Error( 'rest_cannot_edit_others', __( 'Sorry, you are not allowed to create posts as this user.' ), array( 'status' => rest_authorization_required_code() ) );
@@ -589,12 +620,15 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.
 	 */
 	public function update_item_permissions_check( $request ) {
+		$post = $this->get_post( $request['id'] );
+		if ( is_wp_error( $post ) ) {
+			return $post;
+		}
 
-		$post = get_post( $request['id'] );
 		$post_type = get_post_type_object( $this->post_type );
 
 		if ( $post && ! $this->check_update_permission( $post ) ) {
 			return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this post.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
@@ -622,15 +656,13 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function update_item( $request ) {
-		$id   = (int) $request['id'];
-		$post = get_post( $id );
-
-		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
-			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
+		$valid_check = $this->get_post( $request['id'] );
+		if ( is_wp_error( $valid_check ) ) {
+			return $valid_check;
 		}
 
 		$post = $this->prepare_item_for_database( $request );
 
 		if ( is_wp_error( $post ) ) {
@@ -712,12 +744,14 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
 	 */
 	public function delete_item_permissions_check( $request ) {
-
-		$post = get_post( $request['id'] );
+		$post = $this->get_post( $request['id'] );
+		if ( is_wp_error( $post ) ) {
+			return $post;
+		}
 
 		if ( $post && ! $this->check_delete_permission( $post ) ) {
 			return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this post.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
 
@@ -732,19 +766,18 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function delete_item( $request ) {
-		$id    = (int) $request['id'];
-		$force = (bool) $request['force'];
-
-		$post = get_post( $id );
-
-		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
-			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
+		$post = $this->get_post( $request['id'] );
+		if ( is_wp_error( $post ) ) {
+			return $post;
 		}
 
+		$id    = $post->ID;
+		$force = (bool) $request['force'];
+
 		$supports_trash = ( EMPTY_TRASH_DAYS > 0 );
 
 		if ( 'attachment' === $post->post_type ) {
 			$supports_trash = $supports_trash && MEDIA_TRASH;
 		}
@@ -899,11 +932,16 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 	protected function prepare_item_for_database( $request ) {
 		$prepared_post = new stdClass;
 
 		// Post ID.
 		if ( isset( $request['id'] ) ) {
-			$prepared_post->ID = absint( $request['id'] );
+			$existing_post = $this->get_post( $request['id'] );
+			if ( is_wp_error( $existing_post ) ) {
+				return $existing_post;
+			}
+
+			$prepared_post->ID = $existing_post->ID;
 		}
 
 		$schema = $this->get_item_schema();
 
 		// Post title.
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php
index 39ef8fe818..c38bd45928 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php
@@ -69,20 +69,36 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
 	 * @see register_rest_route()
 	 */
 	public function register_routes() {
 
 		register_rest_route( $this->namespace, '/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base, array(
+			'args' => array(
+				'parent' => array(
+					'description' => __( 'The ID for the parent of the object.' ),
+					'type'        => 'integer',
+				),
+			),
 			array(
 				'methods'             => WP_REST_Server::READABLE,
 				'callback'            => array( $this, 'get_items' ),
 				'permission_callback' => array( $this, 'get_items_permissions_check' ),
 				'args'                => $this->get_collection_params(),
 			),
 			'schema' => array( $this, 'get_public_item_schema' ),
 		) );
 
 		register_rest_route( $this->namespace, '/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base . '/(?P<id>[\d]+)', array(
+			'args' => array(
+				'parent' => array(
+					'description' => __( 'The ID for the parent of the object.' ),
+					'type'        => 'integer',
+				),
+				'id' => array(
+					'description' => __( 'Unique identifier for the object.' ),
+					'type'        => 'integer',
+				),
+			),
 			array(
 				'methods'             => WP_REST_Server::READABLE,
 				'callback'            => array( $this, 'get_item' ),
 				'permission_callback' => array( $this, 'get_item_permissions_check' ),
 				'args'                => array(
@@ -104,46 +120,90 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
 			'schema' => array( $this, 'get_public_item_schema' ),
 		));
 
 	}
 
+	/**
+	 * Get the parent post, if the ID is valid.
+	 *
+	 * @since 4.7.2
+	 *
+	 * @param int $id Supplied ID.
+	 * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise.
+	 */
+	protected function get_parent( $parent ) {
+		$error = new WP_Error( 'rest_post_invalid_parent', __( 'Invalid post parent ID.' ), array( 'status' => 404 ) );
+		if ( (int) $parent <= 0 ) {
+			return $error;
+		}
+
+		$parent = get_post( (int) $parent );
+		if ( empty( $parent ) || empty( $parent->ID ) || $this->parent_post_type !== $parent->post_type ) {
+			return $error;
+		}
+
+		return $parent;
+	}
+
 	/**
 	 * Checks if a given request has access to get revisions.
 	 *
 	 * @since 4.7.0
 	 * @access public
 	 *
 	 * @param WP_REST_Request $request Full data about the request.
 	 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
 	 */
 	public function get_items_permissions_check( $request ) {
-
-		$parent = get_post( $request['parent'] );
-		if ( ! $parent ) {
-			return true;
+		$parent = $this->get_parent( $request['parent'] );
+		if ( is_wp_error( $parent ) ) {
+			return $parent;
 		}
+
 		$parent_post_type_obj = get_post_type_object( $parent->post_type );
 		if ( ! current_user_can( $parent_post_type_obj->cap->edit_post, $parent->ID ) ) {
 			return new WP_Error( 'rest_cannot_read', __( 'Sorry, you are not allowed to view revisions of this post.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
 
 		return true;
 	}
 
+	/**
+	 * Get the revision, if the ID is valid.
+	 *
+	 * @since 4.7.2
+	 *
+	 * @param int $id Supplied ID.
+	 * @return WP_Post|WP_Error Revision post object if ID is valid, WP_Error otherwise.
+	 */
+	protected function get_revision( $id ) {
+		$error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid revision ID.' ), array( 'status' => 404 ) );
+		if ( (int) $id <= 0 ) {
+			return $error;
+		}
+
+		$revision = get_post( (int) $id );
+		if ( empty( $revision ) || empty( $revision->ID ) || 'revision' !== $revision->post_type ) {
+			return $error;
+		}
+
+		return $revision;
+	}
+
 	/**
 	 * Gets a collection of revisions.
 	 *
 	 * @since 4.7.0
 	 * @access public
 	 *
 	 * @param WP_REST_Request $request Full data about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function get_items( $request ) {
-		$parent = get_post( $request['parent'] );
-		if ( ! $request['parent'] || ! $parent || $this->parent_post_type !== $parent->post_type ) {
-			return new WP_Error( 'rest_post_invalid_parent', __( 'Invalid post parent ID.' ), array( 'status' => 404 ) );
+		$parent = $this->get_parent( $request['parent'] );
+		if ( is_wp_error( $parent ) ) {
+			return $parent;
 		}
 
 		$revisions = wp_get_post_revisions( $request['parent'] );
 
 		$response = array();
@@ -175,18 +235,18 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full data about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function get_item( $request ) {
-		$parent = get_post( $request['parent'] );
-		if ( ! $request['parent'] || ! $parent || $this->parent_post_type !== $parent->post_type ) {
-			return new WP_Error( 'rest_post_invalid_parent', __( 'Invalid post parent ID.' ), array( 'status' => 404 ) );
+		$parent = $this->get_parent( $request['parent'] );
+		if ( is_wp_error( $parent ) ) {
+			return $parent;
 		}
 
-		$revision = get_post( $request['id'] );
-		if ( ! $revision || 'revision' !== $revision->post_type ) {
-			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid revision ID.' ), array( 'status' => 404 ) );
+		$revision = $this->get_revision( $request['id'] );
+		if ( is_wp_error( $revision ) ) {
+			return $revision;
 		}
 
 		$response = $this->prepare_item_for_response( $revision, $request );
 		return rest_ensure_response( $response );
 	}
@@ -199,22 +259,27 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
 	 *
 	 * @param  WP_REST_Request $request Full details about the request.
 	 * @return bool|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
 	 */
 	public function delete_item_permissions_check( $request ) {
+		$parent = $this->get_parent( $request['parent'] );
+		if ( is_wp_error( $parent ) ) {
+			return $parent;
+		}
+
+		$revision = $this->get_revision( $request['id'] );
+		if ( is_wp_error( $revision ) ) {
+			return $revision;
+		}
 
 		$response = $this->get_items_permissions_check( $request );
 		if ( ! $response || is_wp_error( $response ) ) {
 			return $response;
 		}
 
-		$post = get_post( $request['id'] );
-		if ( ! $post ) {
-			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid revision ID.' ), array( 'status' => 404 ) );
-		}
 		$post_type = get_post_type_object( 'revision' );
-		return current_user_can( $post_type->cap->delete_post, $post->ID );
+		return current_user_can( $post_type->cap->delete_post, $revision->ID );
 	}
 
 	/**
 	 * Deletes a single revision.
 	 *
@@ -223,18 +288,22 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return true|WP_Error True on success, or WP_Error object on failure.
 	 */
 	public function delete_item( $request ) {
+		$revision = $this->get_revision( $request['id'] );
+		if ( is_wp_error( $revision ) ) {
+			return $revision;
+		}
+
 		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
 
 		// We don't support trashing for revisions.
 		if ( ! $force ) {
 			return new WP_Error( 'rest_trash_not_supported', __( 'Revisions do not support trashing. Set force=true to delete.' ), array( 'status' => 501 ) );
 		}
 
-		$revision = get_post( $request['id'] );
 		$previous = $this->prepare_item_for_response( $revision, $request );
 
 		$result = wp_delete_post( $request['id'], true );
 
 		/**
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php
index 0fe91ee432..b46562c9c4 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php
@@ -46,10 +46,16 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
 			),
 			'schema' => array( $this, 'get_public_item_schema' ),
 		) );
 
 		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<taxonomy>[\w-]+)', array(
+			'args' => array(
+				'taxonomy' => array(
+					'description'  => __( 'An alphanumeric identifier for the taxonomy.' ),
+					'type'         => 'string',
+				),
+			),
 			array(
 				'methods'         => WP_REST_Server::READABLE,
 				'callback'        => array( $this, 'get_item' ),
 				'permission_callback' => array( $this, 'get_item_permissions_check' ),
 				'args'            => array(
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
index 16882522c5..9d33eaa475 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
@@ -94,10 +94,16 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 			),
 			'schema' => array( $this, 'get_public_item_schema' ),
 		) );
 
 		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
+			'args' => array(
+				'id' => array(
+					'description' => __( 'Unique identifier for the term.' ),
+					'type'        => 'integer',
+				),
+			),
 			array(
 				'methods'             => WP_REST_Server::READABLE,
 				'callback'            => array( $this, 'get_item' ),
 				'permission_callback' => array( $this, 'get_item_permissions_check' ),
 				'args'                => array(
@@ -106,11 +112,11 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 			),
 			array(
 				'methods'             => WP_REST_Server::EDITABLE,
 				'callback'            => array( $this, 'update_item' ),
 				'permission_callback' => array( $this, 'update_item_permissions_check' ),
-				'args'                 => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
+				'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
 			),
 			array(
 				'methods'             => WP_REST_Server::DELETABLE,
 				'callback'            => array( $this, 'delete_item' ),
 				'permission_callback' => array( $this, 'delete_item_permissions_check' ),
@@ -285,25 +291,53 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 		}
 
 		return $response;
 	}
 
+	/**
+	 * Get the term, if the ID is valid.
+	 *
+	 * @since 4.7.2
+	 *
+	 * @param int $id Supplied ID.
+	 * @return WP_Term|WP_Error Term object if ID is valid, WP_Error otherwise.
+	 */
+	protected function get_term( $id ) {
+		$error = new WP_Error( 'rest_term_invalid', __( 'Term does not exist.' ), array( 'status' => 404 ) );
+
+		if ( ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
+			return $error;
+		}
+
+		if ( (int) $id <= 0 ) {
+			return $error;
+		}
+
+		$term = get_term( (int) $id, $this->taxonomy );
+		if ( empty( $term ) || $term->taxonomy !== $this->taxonomy ) {
+			return $error;
+		}
+
+		return $term;
+	}
+
 	/**
 	 * Checks if a request has access to read or edit the specified term.
 	 *
 	 * @since 4.7.0
 	 * @access public
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return bool|WP_Error True if the request has read access for the item, otherwise false or WP_Error object.
 	 */
 	public function get_item_permissions_check( $request ) {
-		$tax_obj = get_taxonomy( $this->taxonomy );
-		if ( ! $tax_obj || ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
-			return false;
+		$term = $this->get_term( $request['id'] );
+		if ( is_wp_error( $term ) ) {
+			return $term;
 		}
-		if ( 'edit' === $request['context'] && ! current_user_can( 'edit_term', (int) $request['id'] ) ) {
+
+		if ( 'edit' === $request['context'] && ! current_user_can( 'edit_term', $term->term_id ) ) {
 			return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this term.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
 		return true;
 	}
 
@@ -315,17 +349,11 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function get_item( $request ) {
-
-		$term = get_term( (int) $request['id'], $this->taxonomy );
-
-		if ( ! $term || $term->taxonomy !== $this->taxonomy ) {
-			return new WP_Error( 'rest_term_invalid', __( 'Term does not exist.' ), array( 'status' => 404 ) );
-		}
-
+		$term = $this->get_term( $request['id'] );
 		if ( is_wp_error( $term ) ) {
 			return $term;
 		}
 
 		$response = $this->prepare_item_for_response( $term, $request );
@@ -443,19 +471,13 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return bool|WP_Error True if the request has access to update the item, false or WP_Error object otherwise.
 	 */
 	public function update_item_permissions_check( $request ) {
-
-		if ( ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
-			return false;
-		}
-
-		$term = get_term( (int) $request['id'], $this->taxonomy );
-
-		if ( ! $term ) {
-			return new WP_Error( 'rest_term_invalid', __( 'Term does not exist.' ), array( 'status' => 404 ) );
+		$term = $this->get_term( $request['id'] );
+		if ( is_wp_error( $term ) ) {
+			return $term;
 		}
 
 		if ( ! current_user_can( 'edit_term', $term->term_id ) ) {
 			return new WP_Error( 'rest_cannot_update', __( 'Sorry, you are not allowed to edit this term.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
@@ -471,10 +493,15 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function update_item( $request ) {
+		$term = $this->get_term( $request['id'] );
+		if ( is_wp_error( $term ) ) {
+			return $term;
+		}
+
 		if ( isset( $request['parent'] ) ) {
 			if ( ! is_taxonomy_hierarchical( $this->taxonomy ) ) {
 				return new WP_Error( 'rest_taxonomy_not_hierarchical', __( 'Can not set parent term, taxonomy is not hierarchical.' ), array( 'status' => 400 ) );
 			}
 
@@ -485,29 +512,27 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 			}
 		}
 
 		$prepared_term = $this->prepare_item_for_database( $request );
 
-		$term = get_term( (int) $request['id'], $this->taxonomy );
-
 		// Only update the term if we haz something to update.
 		if ( ! empty( $prepared_term ) ) {
 			$update = wp_update_term( $term->term_id, $term->taxonomy, wp_slash( (array) $prepared_term ) );
 
 			if ( is_wp_error( $update ) ) {
 				return $update;
 			}
 		}
 
-		$term = get_term( (int) $request['id'], $this->taxonomy );
+		$term = get_term( $term->term_id, $this->taxonomy );
 
 		/** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php */
 		do_action( "rest_insert_{$this->taxonomy}", $term, $request, false );
 
 		$schema = $this->get_item_schema();
 		if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) {
-			$meta_update = $this->meta->update_value( $request['meta'], (int) $request['id'] );
+			$meta_update = $this->meta->update_value( $request['meta'], $term->term_id );
 
 			if ( is_wp_error( $meta_update ) ) {
 				return $meta_update;
 			}
 		}
@@ -533,18 +558,13 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return bool|WP_Error True if the request has access to delete the item, otherwise false or WP_Error object.
 	 */
 	public function delete_item_permissions_check( $request ) {
-		if ( ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
-			return false;
-		}
-
-		$term = get_term( (int) $request['id'], $this->taxonomy );
-
-		if ( ! $term ) {
-			return new WP_Error( 'rest_term_invalid', __( 'Term does not exist.' ), array( 'status' => 404 ) );
+		$term = $this->get_term( $request['id'] );
+		if ( is_wp_error( $term ) ) {
+			return $term;
 		}
 
 		if ( ! current_user_can( 'delete_term', $term->term_id ) ) {
 			return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this term.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
@@ -560,20 +580,22 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function delete_item( $request ) {
+		$term = $this->get_term( $request['id'] );
+		if ( is_wp_error( $term ) ) {
+			return $term;
+		}
 
 		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
 
 		// We don't support trashing for terms.
 		if ( ! $force ) {
 			return new WP_Error( 'rest_trash_not_supported', __( 'Terms do not support trashing. Set force=true to delete.' ), array( 'status' => 501 ) );
 		}
 
-		$term = get_term( (int) $request['id'], $this->taxonomy );
-
 		$request->set_param( 'context', 'view' );
 
 		$previous = $this->prepare_item_for_response( $term, $request );
 
 		$retval = wp_delete_term( $term->term_id, $term->taxonomy );
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
index 4f6c378a11..802eb649c3 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
@@ -63,10 +63,16 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
 			),
 			'schema' => array( $this, 'get_public_item_schema' ),
 		) );
 
 		register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
+			'args' => array(
+				'id' => array(
+					'description' => __( 'Unique identifier for the user.' ),
+					'type'        => 'integer',
+				),
+			),
 			array(
 				'methods'             => WP_REST_Server::READABLE,
 				'callback'            => array( $this, 'get_item' ),
 				'permission_callback' => array( $this, 'get_item_permissions_check' ),
 				'args'                => array(
@@ -324,36 +330,56 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
 		}
 
 		return $response;
 	}
 
+	/**
+	 * Get the user, if the ID is valid.
+	 *
+	 * @since 4.7.2
+	 *
+	 * @param int $id Supplied ID.
+	 * @return WP_User|WP_Error True if ID is valid, WP_Error otherwise.
+	 */
+	protected function get_user( $id ) {
+		$error = new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
+		if ( (int) $id <= 0 ) {
+			return $error;
+		}
+
+		$user = get_userdata( (int) $id );
+		if ( empty( $user ) || ! $user->exists() ) {
+			return $error;
+		}
+
+		return $user;
+	}
+
 	/**
 	 * Checks if a given request has access to read a user.
 	 *
 	 * @since 4.7.0
 	 * @access public
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return true|WP_Error True if the request has read access for the item, otherwise WP_Error object.
 	 */
 	public function get_item_permissions_check( $request ) {
+		$user = $this->get_user( $request['id'] );
+		if ( is_wp_error( $user ) ) {
+			return $user;
+		}
 
-		$id = (int) $request['id'];
-		$user = get_userdata( $id );
 		$types = get_post_types( array( 'show_in_rest' => true ), 'names' );
 
-		if ( empty( $id ) || empty( $user->ID ) ) {
-			return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
-		}
-
-		if ( get_current_user_id() === $id ) {
+		if ( get_current_user_id() === $user->ID ) {
 			return true;
 		}
 
 		if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) {
 			return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) );
-		} elseif ( ! count_user_posts( $id, $types ) && ! current_user_can( 'edit_user', $id ) && ! current_user_can( 'list_users' ) ) {
+		} elseif ( ! count_user_posts( $user->ID, $types ) && ! current_user_can( 'edit_user', $user->ID ) && ! current_user_can( 'list_users' ) ) {
 			return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to list users.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
 
 		return true;
 	}
@@ -366,15 +392,13 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function get_item( $request ) {
-		$id   = (int) $request['id'];
-		$user = get_userdata( $id );
-
-		if ( empty( $id ) || empty( $user->ID ) ) {
-			return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
+		$user = $this->get_user( $request['id'] );
+		if ( is_wp_error( $user ) ) {
+			return $user;
 		}
 
 		$user = $this->prepare_item_for_response( $user, $request );
 		$response = rest_ensure_response( $user );
 
@@ -540,14 +564,16 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.
 	 */
 	public function update_item_permissions_check( $request ) {
+		$user = $this->get_user( $request['id'] );
+		if ( is_wp_error( $user ) ) {
+			return $user;
+		}
 
-		$id = (int) $request['id'];
-
-		if ( ! current_user_can( 'edit_user', $id ) ) {
+		if ( ! current_user_can( 'edit_user', $user->ID ) ) {
 			return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this user.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
 
 		if ( ! empty( $request['roles'] ) && ! current_user_can( 'edit_users' ) ) {
 			return new WP_Error( 'rest_cannot_edit_roles', __( 'Sorry, you are not allowed to edit roles of this user.' ), array( 'status' => rest_authorization_required_code() ) );
@@ -564,12 +590,16 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 	 */
 	public function update_item( $request ) {
-		$id   = (int) $request['id'];
-		$user = get_userdata( $id );
+		$user = $this->get_user( $request['id'] );
+		if ( is_wp_error( $user ) ) {
+			return $user;
+		}
+
+		$id = $user->ID;
 
 		if ( ! $user ) {
 			return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
 		}
 
@@ -680,14 +710,16 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
 	 * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
 	 */
 	public function delete_item_permissions_check( $request ) {
+		$user = $this->get_user( $request['id'] );
+		if ( is_wp_error( $user ) ) {
+			return $user;
+		}
 
-		$id = (int) $request['id'];
-
-		if ( ! current_user_can( 'delete_user', $id ) ) {
+		if ( ! current_user_can( 'delete_user', $user->ID ) ) {
 			return new WP_Error( 'rest_user_cannot_delete', __( 'Sorry, you are not allowed to delete this user.' ), array( 'status' => rest_authorization_required_code() ) );
 		}
 
 		return true;
 	}
@@ -704,26 +736,24 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
 	public function delete_item( $request ) {
 		// We don't support delete requests in multisite.
 		if ( is_multisite() ) {
 			return new WP_Error( 'rest_cannot_delete', __( 'The user cannot be deleted.' ), array( 'status' => 501 ) );
 		}
+		$user = $this->get_user( $request['id'] );
+		if ( is_wp_error( $user ) ) {
+			return $user;
+		}
 
-		$id       = (int) $request['id'];
+		$id       = $user->ID;
 		$reassign = false === $request['reassign'] ? null : absint( $request['reassign'] );
 		$force    = isset( $request['force'] ) ? (bool) $request['force'] : false;
 
 		// We don't support trashing for users.
 		if ( ! $force ) {
 			return new WP_Error( 'rest_trash_not_supported', __( 'Users do not support trashing. Set force=true to delete.' ), array( 'status' => 501 ) );
 		}
 
-		$user = get_userdata( $id );
-
-		if ( ! $user ) {
-			return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
-		}
-
 		if ( ! empty( $reassign ) ) {
 			if ( $reassign === $id || ! get_userdata( $reassign ) ) {
 				return new WP_Error( 'rest_user_invalid_reassign', __( 'Invalid user ID for reassignment.' ), array( 'status' => 400 ) );
 			}
 		}
diff --git a/wp-includes/version.php b/wp-includes/version.php
index fc69fd2007..c26e7a0fee 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -2,11 +2,11 @@
 /**
  * The WordPress version string
  *
  * @global string $wp_version
  */
-$wp_version = '4.8-alpha-39952';
+$wp_version = '4.8-alpha-39954';
 
 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
  *
  * @global int $wp_db_version

Vulnerable code: 		if ( ! is_numeric( $arg_group ) ) {
		$id = (int) $request['id'];

		$comment = get_comment( $id );

		if ( ! $comment ) {
			return true;
		$id = (int) $request['id'];

		$comment = get_comment( $id );
		if ( empty( $comment ) ) {
			return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
		}

		if ( ! empty( $comment->comment_post_ID ) ) {
			$post = get_post( $comment->comment_post_ID );
			if ( empty( $post ) ) {
				return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
			}
		$id = (int) $request['id'];

		$comment = get_comment( $id );

		if ( $comment && ! $this->check_edit_permission( $comment ) ) {
		$id = (int) $request['id'];

		$comment = get_comment( $id );

		if ( empty( $comment ) ) {
			return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
		$id      = (int) $request['id'];
		$comment = get_comment( $id );

		if ( ! $comment ) {
			return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
		$id    = (int) $request['id'];
		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;

		$comment = get_comment( $id );

		if ( empty( $comment ) ) {
			return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );

		$post = get_post( (int) $request['id'] );
		$id   = (int) $request['id'];
		$post = get_post( $id );

		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
			$response->link_header( 'alternate',  get_permalink( $id ), array( 'type' => 'text/html' ) );
		$post = get_post( $request['id'] );
		$id   = (int) $request['id'];
		$post = get_post( $id );

		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );

		$post = get_post( $request['id'] );
		$id    = (int) $request['id'];
		$force = (bool) $request['force'];

		$post = get_post( $id );

		if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
			$prepared_post->ID = absint( $request['id'] );

		$parent = get_post( $request['parent'] );
		if ( ! $parent ) {
			return true;
		$parent = get_post( $request['parent'] );
		if ( ! $request['parent'] || ! $parent || $this->parent_post_type !== $parent->post_type ) {
			return new WP_Error( 'rest_post_invalid_parent', __( 'Invalid post parent ID.' ), array( 'status' => 404 ) );
		$parent = get_post( $request['parent'] );
		if ( ! $request['parent'] || ! $parent || $this->parent_post_type !== $parent->post_type ) {
			return new WP_Error( 'rest_post_invalid_parent', __( 'Invalid post parent ID.' ), array( 'status' => 404 ) );
		$revision = get_post( $request['id'] );
		if ( ! $revision || 'revision' !== $revision->post_type ) {
			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid revision ID.' ), array( 'status' => 404 ) );
		$post = get_post( $request['id'] );
		if ( ! $post ) {
			return new WP_Error( 'rest_post_invalid_id', __( 'Invalid revision ID.' ), array( 'status' => 404 ) );
		}
		return current_user_can( $post_type->cap->delete_post, $post->ID );
		$revision = get_post( $request['id'] );
				'args'                 => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
		$tax_obj = get_taxonomy( $this->taxonomy );
		if ( ! $tax_obj || ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
			return false;
		if ( 'edit' === $request['context'] && ! current_user_can( 'edit_term', (int) $request['id'] ) ) {

		$term = get_term( (int) $request['id'], $this->taxonomy );

		if ( ! $term || $term->taxonomy !== $this->taxonomy ) {
			return new WP_Error( 'rest_term_invalid', __( 'Term does not exist.' ), array( 'status' => 404 ) );
		}


		if ( ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
			return false;
		}

		$term = get_term( (int) $request['id'], $this->taxonomy );

		if ( ! $term ) {
			return new WP_Error( 'rest_term_invalid', __( 'Term does not exist.' ), array( 'status' => 404 ) );
		$term = get_term( (int) $request['id'], $this->taxonomy );

		$term = get_term( (int) $request['id'], $this->taxonomy );
			$meta_update = $this->meta->update_value( $request['meta'], (int) $request['id'] );
		if ( ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
			return false;
		}

		$term = get_term( (int) $request['id'], $this->taxonomy );

		if ( ! $term ) {
			return new WP_Error( 'rest_term_invalid', __( 'Term does not exist.' ), array( 'status' => 404 ) );
		$term = get_term( (int) $request['id'], $this->taxonomy );

		$id = (int) $request['id'];
		$user = get_userdata( $id );
		if ( empty( $id ) || empty( $user->ID ) ) {
			return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
		}

		if ( get_current_user_id() === $id ) {
		} elseif ( ! count_user_posts( $id, $types ) && ! current_user_can( 'edit_user', $id ) && ! current_user_can( 'list_users' ) ) {
		$id   = (int) $request['id'];
		$user = get_userdata( $id );

		if ( empty( $id ) || empty( $user->ID ) ) {
			return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
		$id = (int) $request['id'];

		if ( ! current_user_can( 'edit_user', $id ) ) {
		$id   = (int) $request['id'];
		$user = get_userdata( $id );
		$id = (int) $request['id'];

		if ( ! current_user_can( 'delete_user', $id ) ) {
		$id       = (int) $request['id'];
		$user = get_userdata( $id );

		if ( ! $user ) {
			return new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
		}

$wp_version = '4.8-alpha-39952';
Fixed code: 	if ( isset( $args['args'] ) ) {
		$common_args = $args['args'];
		unset( $args['args'] );
	} else {
		$common_args = array();
	}

		if ( ! is_numeric( $key ) ) {
		$arg_group['args'] = array_merge( $common_args, $arg_group['args'] );
			'args' => array(
				'id' => array(
					'description' => __( 'Unique identifier for the object.' ),
					'type'        => 'integer',
				),
			),
	/**
	 * Get the comment, if the ID is valid.
	 *
	 * @since 4.7.2
	 *
	 * @param int $id Supplied ID.
	 * @return WP_Comment|WP_Error Comment object if ID is valid, WP_Error otherwise.
	 */
	protected function get_comment( $id ) {
		$error = new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
		if ( (int) $id <= 0 ) {
			return $error;
		}

		$id = (int) $id;
		$comment = get_comment( $id );
		if ( empty( $comment ) ) {
			return $error;
		}

		if ( ! empty( $comment->comment_post_ID ) ) {
			$post = get_post( (int) $comment->comment_post_ID );
			if ( empty( $post ) ) {
				return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
			}
		}

		return $comment;
	}

		$comment = $this->get_comment( $request['id'] );
		if ( is_wp_error( $comment ) ) {
			return $comment;
		$comment = $this->get_comment( $request['id'] );
		if ( is_wp_error( $comment ) ) {
			return $comment;
		$comment = $this->get_comment( $request['id'] );
		if ( is_wp_error( $comment ) ) {
			return $comment;
		}
		if ( ! $this->check_edit_permission( $comment ) ) {
		$comment = $this->get_comment( $request['id'] );
		if ( is_wp_error( $comment ) ) {
			return $comment;
		$id = $comment->comment_ID;

		$comment = $this->get_comment( $request['id'] );
		if ( is_wp_error( $comment ) ) {
			return $comment;
		$comment = $this->get_comment( $request['id'] );
		if ( is_wp_error( $comment ) ) {
			return $comment;
		$force = isset( $request['force'] ) ? (bool) $request['force'] : false;

			'args' => array(
				'status' => array(
					'description' => __( 'An alphanumeric identifier for the status.' ),
					'type'        => 'string',
				),
			),
			'args' => array(
				'type' => array(
					'description' => __( 'An alphanumeric identifier for the post type.' ),
					'type'        => 'string',
				),
			),
			'args' => array(
				'id' => array(
					'description' => __( 'Unique identifier for the object.' ),
					'type'        => 'integer',
				),
			),
	/**
	 * Get the post, if the ID is valid.
	 *
	 * @since 4.7.2
	 *
	 * @param int $id Supplied ID.
	 * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise.
	 */
	protected function get_post( $id ) {
		$error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
		if ( (int) $id <= 0 ) {
			return $error;
		}

		$post = get_post( (int) $id );
		if ( empty( $post ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
			return $error;
		}

		return $post;
	}

		$post = $this->get_post( $request['id'] );
		if ( is_wp_error( $post ) ) {
			return $post;
		}
		$post = $this->get_post( $request['id'] );
		if ( is_wp_error( $post ) ) {
			return $post;
			$response->link_header( 'alternate',  get_permalink( $post->ID ), array( 'type' => 'text/html' ) );
		if ( ! empty( $request['id'] ) ) {
			return new WP_Error( 'rest_post_exists', __( 'Cannot create existing post.' ), array( 'status' => 400 ) );
		}
		$post = $this->get_post( $request['id'] );
		if ( is_wp_error( $post ) ) {
			return $post;
		}
		$valid_check = $this->get_post( $request['id'] );
		if ( is_wp_error( $valid_check ) ) {
			return $valid_check;
		$post = $this->get_post( $request['id'] );
		if ( is_wp_error( $post ) ) {
			return $post;
		}
		$post = $this->get_post( $request['id'] );
		if ( is_wp_error( $post ) ) {
			return $post;
		$id    = $post->ID;
		$force = (bool) $request['force'];

			$existing_post = $this->get_post( $request['id'] );
			if ( is_wp_error( $existing_post ) ) {
				return $existing_post;
			}

			$prepared_post->ID = $existing_post->ID;
			'args' => array(
				'parent' => array(
					'description' => __( 'The ID for the parent of the object.' ),
					'type'        => 'integer',
				),
			),
			'args' => array(
				'parent' => array(
					'description' => __( 'The ID for the parent of the object.' ),
					'type'        => 'integer',
				),
				'id' => array(
					'description' => __( 'Unique identifier for the object.' ),
					'type'        => 'integer',
				),
			),
	/**
	 * Get the parent post, if the ID is valid.
	 *
	 * @since 4.7.2
	 *
	 * @param int $id Supplied ID.
	 * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise.
	 */
	protected function get_parent( $parent ) {
		$error = new WP_Error( 'rest_post_invalid_parent', __( 'Invalid post parent ID.' ), array( 'status' => 404 ) );
		if ( (int) $parent <= 0 ) {
			return $error;
		}

		$parent = get_post( (int) $parent );
		if ( empty( $parent ) || empty( $parent->ID ) || $this->parent_post_type !== $parent->post_type ) {
			return $error;
		}

		return $parent;
	}

		$parent = $this->get_parent( $request['parent'] );
		if ( is_wp_error( $parent ) ) {
			return $parent;

	/**
	 * Get the revision, if the ID is valid.
	 *
	 * @since 4.7.2
	 *
	 * @param int $id Supplied ID.
	 * @return WP_Post|WP_Error Revision post object if ID is valid, WP_Error otherwise.
	 */
	protected function get_revision( $id ) {
		$error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid revision ID.' ), array( 'status' => 404 ) );
		if ( (int) $id <= 0 ) {
			return $error;
		}

		$revision = get_post( (int) $id );
		if ( empty( $revision ) || empty( $revision->ID ) || 'revision' !== $revision->post_type ) {
			return $error;
		}

		return $revision;
	}

		$parent = $this->get_parent( $request['parent'] );
		if ( is_wp_error( $parent ) ) {
			return $parent;
		$parent = $this->get_parent( $request['parent'] );
		if ( is_wp_error( $parent ) ) {
			return $parent;
		$revision = $this->get_revision( $request['id'] );
		if ( is_wp_error( $revision ) ) {
			return $revision;
		$parent = $this->get_parent( $request['parent'] );
		if ( is_wp_error( $parent ) ) {
			return $parent;
		}

		$revision = $this->get_revision( $request['id'] );
		if ( is_wp_error( $revision ) ) {
			return $revision;
		}
		return current_user_can( $post_type->cap->delete_post, $revision->ID );
		$revision = $this->get_revision( $request['id'] );
		if ( is_wp_error( $revision ) ) {
			return $revision;
		}

			'args' => array(
				'taxonomy' => array(
					'description'  => __( 'An alphanumeric identifier for the taxonomy.' ),
					'type'         => 'string',
				),
			),
			'args' => array(
				'id' => array(
					'description' => __( 'Unique identifier for the term.' ),
					'type'        => 'integer',
				),
			),
				'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
	/**
	 * Get the term, if the ID is valid.
	 *
	 * @since 4.7.2
	 *
	 * @param int $id Supplied ID.
	 * @return WP_Term|WP_Error Term object if ID is valid, WP_Error otherwise.
	 */
	protected function get_term( $id ) {
		$error = new WP_Error( 'rest_term_invalid', __( 'Term does not exist.' ), array( 'status' => 404 ) );

		if ( ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
			return $error;
		}

		if ( (int) $id <= 0 ) {
			return $error;
		}

		$term = get_term( (int) $id, $this->taxonomy );
		if ( empty( $term ) || $term->taxonomy !== $this->taxonomy ) {
			return $error;
		}

		return $term;
	}

		$term = $this->get_term( $request['id'] );
		if ( is_wp_error( $term ) ) {
			return $term;

		if ( 'edit' === $request['context'] && ! current_user_can( 'edit_term', $term->term_id ) ) {
		$term = $this->get_term( $request['id'] );
		$term = $this->get_term( $request['id'] );
		if ( is_wp_error( $term ) ) {
			return $term;
		$term = $this->get_term( $request['id'] );
		if ( is_wp_error( $term ) ) {
			return $term;
		}

		$term = get_term( $term->term_id, $this->taxonomy );
			$meta_update = $this->meta->update_value( $request['meta'], $term->term_id );
		$term = $this->get_term( $request['id'] );
		if ( is_wp_error( $term ) ) {
			return $term;
		$term = $this->get_term( $request['id'] );
		if ( is_wp_error( $term ) ) {
			return $term;
		}
			'args' => array(
				'id' => array(
					'description' => __( 'Unique identifier for the user.' ),
					'type'        => 'integer',
				),
			),
	/**
	 * Get the user, if the ID is valid.
	 *
	 * @since 4.7.2
	 *
	 * @param int $id Supplied ID.
	 * @return WP_User|WP_Error True if ID is valid, WP_Error otherwise.
	 */
	protected function get_user( $id ) {
		$error = new WP_Error( 'rest_user_invalid_id', __( 'Invalid user ID.' ), array( 'status' => 404 ) );
		if ( (int) $id <= 0 ) {
			return $error;
		}

		$user = get_userdata( (int) $id );
		if ( empty( $user ) || ! $user->exists() ) {
			return $error;
		}

		return $user;
	}

		$user = $this->get_user( $request['id'] );
		if ( is_wp_error( $user ) ) {
			return $user;
		}
		if ( get_current_user_id() === $user->ID ) {
		} elseif ( ! count_user_posts( $user->ID, $types ) && ! current_user_can( 'edit_user', $user->ID ) && ! current_user_can( 'list_users' ) ) {
		$user = $this->get_user( $request['id'] );
		if ( is_wp_error( $user ) ) {
			return $user;
		$user = $this->get_user( $request['id'] );
		if ( is_wp_error( $user ) ) {
			return $user;
		}
		if ( ! current_user_can( 'edit_user', $user->ID ) ) {
		$user = $this->get_user( $request['id'] );
		if ( is_wp_error( $user ) ) {
			return $user;
		}

		$id = $user->ID;
		$user = $this->get_user( $request['id'] );
		if ( is_wp_error( $user ) ) {
			return $user;
		}
		if ( ! current_user_can( 'delete_user', $user->ID ) ) {
		$user = $this->get_user( $request['id'] );
		if ( is_wp_error( $user ) ) {
			return $user;
		}
		$id       = $user->ID;
$wp_version = '4.8-alpha-39954';