Index: src/wp-includes/capabilities.php
===================================================================
--- src/wp-includes/capabilities.php	(revision 39046)
+++ src/wp-includes/capabilities.php	(working copy)
@@ -242,56 +242,106 @@
 	case 'edit_post_meta':
 	case 'delete_post_meta':
 	case 'add_post_meta':
-		$post = get_post( $args[0] );
-		if ( ! $post ) {
+	case 'edit_comment_meta':
+	case 'delete_comment_meta':
+	case 'add_comment_meta':
+	case 'edit_term_meta':
+	case 'delete_term_meta':
+	case 'add_term_meta':
+	case 'edit_user_meta':
+	case 'delete_user_meta':
+	case 'add_user_meta':
+		list( $_, $object_type, $_ ) = explode( '_', $cap );
+		$object_id = (int) $args[0];
+
+		switch ( $object_type ) {
+			case 'post':
+				$post = get_post( $object_id );
+				if ( ! $post ) {
+					break;
+				}
+
+				$sub_type = get_post_type( $post );
+				break;
+
+			case 'comment':
+				$comment = get_comment( $object_id );
+				if ( ! $comment ) {
+					break;
+				}
+
+				$sub_type = empty( $comment->comment_type ) ? 'comment' : $comment->comment_type;
+				break;
+
+			case 'term':
+				$term = get_term( $object_id );
+				if ( ! $term ) {
+					break;
+				}
+
+				$sub_type = $term->taxonomy;
+				break;
+
+			case 'user':
+				$user = get_user_by( 'id', $object_id );
+				if ( ! $user ) {
+					break;
+				}
+
+				$sub_type = 'user';
+				break;
+		}
+		if ( empty( $sub_type ) ) {
 			$caps[] = 'do_not_allow';
 			break;
 		}
 
-		$post_type = get_post_type( $post );
+		$caps = map_meta_cap( "edit_{$object_type}", $user_id, $object_id );
 
-		$caps = map_meta_cap( 'edit_post', $user_id, $post->ID );
-
 		$meta_key = isset( $args[ 1 ] ) ? $args[ 1 ] : false;
 
-		if ( $meta_key && ( has_filter( "auth_post_meta_{$meta_key}" ) || has_filter( "auth_post_{$post_type}_meta_{$meta_key}" ) ) ) {
+		$has_filter = has_filter( "auth_{$object_type}_meta_{$meta_key}" ) || has_filter( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}" );
+		if ( $meta_key && $has_filter ) {
 			/**
-			 * Filters whether the user is allowed to add post meta to a post.
+			 * Filters whether the user is allowed to add meta to an object.
 			 *
-			 * The dynamic portion of the hook name, `$meta_key`, refers to the
-			 * meta key passed to map_meta_cap().
+			 * The dynamic portions of the hook name `$object_type`, and `$meta_key`, refer
+			 * to the object type (post, comment, term, user) and meta key passed to
+			 * map_meta_cap(), respectively.
 			 *
 			 * @since 3.3.0
 			 *
-			 * @param bool   $allowed  Whether the user can add the post meta. Default false.
-			 * @param string $meta_key The meta key.
-			 * @param int    $post_id  Post ID.
-			 * @param int    $user_id  User ID.
-			 * @param string $cap      Capability name.
-			 * @param array  $caps     User capabilities.
+			 * @param bool   $allowed    Whether the user can add the meta. Default false.
+			 * @param string $meta_key   The meta key.
+			 * @param int    $object_id  Object ID.
+			 * @param int    $user_id    User ID.
+			 * @param string $cap        Capability name.
+			 * @param array  $caps       User capabilities.
 			 */
-			$allowed = apply_filters( "auth_post_meta_{$meta_key}", false, $meta_key, $post->ID, $user_id, $cap, $caps );
+			$allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", false, $meta_key, $object_id, $user_id, $cap, $caps );
 
 			/**
 			 * Filters whether the user is allowed to add post meta to a post of a given type.
 			 *
-			 * The dynamic portions of the hook name, `$meta_key` and `$post_type`,
-			 * refer to the meta key passed to map_meta_cap() and the post type, respectively.
+			 * The dynamic portions of the hook name, `$meta_key`, `$object_type`,
+			 * `$sub_type`, refer to the meta key passed to map_meta_cap(), the object type
+			 * (post, comment, term, user) and the sub-type (post type, comment type,
+			 * taxonomy), respectively.
 			 *
 			 * @since 4.6.0
 			 *
-			 * @param bool   $allowed  Whether the user can add the post meta. Default false.
-			 * @param string $meta_key The meta key.
-			 * @param int    $post_id  Post ID.
-			 * @param int    $user_id  User ID.
-			 * @param string $cap      Capability name.
-			 * @param array  $caps     User capabilities.
+			 * @param bool   $allowed    Whether the user can add the post meta. Default false.
+			 * @param string $meta_key   The meta key.
+			 * @param int    $object_id  Object ID.
+			 * @param int    $user_id    User ID.
+			 * @param string $cap        Capability name.
+			 * @param array  $caps       User capabilities.
 			 */
-			$allowed = apply_filters( "auth_post_{$post_type}_meta_{$meta_key}", $allowed, $meta_key, $post->ID, $user_id, $cap, $caps );
+			$allowed = apply_filters( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
 
 			if ( ! $allowed )
 				$caps[] = $cap;
-		} elseif ( $meta_key && is_protected_meta( $meta_key, 'post' ) ) {
+		} elseif ( $meta_key && is_protected_meta( $meta_key, $object_type ) ) {
 			$caps[] = $cap;
 		}
 		break;
Index: src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php
===================================================================
--- src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php	(revision 39046)
+++ src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php	(working copy)
@@ -122,7 +122,6 @@
 	 */
 	public function update_value( $request, $object_id ) {
 		$fields = $this->get_registered_fields();
-
 		foreach ( $fields as $name => $args ) {
 			if ( ! array_key_exists( $name, $request ) ) {
 				continue;
@@ -159,7 +158,8 @@
 	 * @return bool|WP_Error True if meta field is deleted, WP_Error otherwise.
 	 */
 	protected function delete_meta_value( $object_id, $name ) {
-		if ( ! current_user_can( 'delete_post_meta', $object_id, $name ) ) {
+		$meta_type = $this->get_meta_type();
+		if ( ! current_user_can( "delete_{$meta_type}_meta", $object_id, $name ) ) {
 			return new WP_Error(
 				'rest_cannot_delete',
 				sprintf( __( 'You do not have permission to edit the %s custom field.' ), $name ),
@@ -167,7 +167,7 @@
 			);
 		}
 
-		if ( ! delete_metadata( $this->get_meta_type(), $object_id, wp_slash( $name ) ) ) {
+		if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $name ) ) ) {
 			return new WP_Error(
 				'rest_meta_database_error',
 				__( 'Could not delete meta value from database.' ),
@@ -192,7 +192,8 @@
 	 * @return bool|WP_Error True if meta fields are updated, WP_Error otherwise.
 	 */
 	protected function update_multi_meta_value( $object_id, $name, $values ) {
-		if ( ! current_user_can( 'edit_post_meta', $object_id, $name ) ) {
+		$meta_type = $this->get_meta_type();
+		if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $name ) ) {
 			return new WP_Error(
 				'rest_cannot_update',
 				sprintf( __( 'You do not have permission to edit the %s custom field.' ), $name ),
@@ -200,7 +201,7 @@
 			);
 		}
 
-		$current = get_metadata( $this->get_meta_type(), $object_id, $name, false );
+		$current = get_metadata( $meta_type, $object_id, $name, false );
 
 		$to_remove = $current;
 		$to_add    = $values;
@@ -227,7 +228,7 @@
 		$to_remove = array_unique( $to_remove );
 
 		foreach ( $to_remove as $value ) {
-			if ( ! delete_metadata( $this->get_meta_type(), $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
+			if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
 				return new WP_Error(
 					'rest_meta_database_error',
 					__( 'Could not update meta value in database.' ),
@@ -237,7 +238,7 @@
 		}
 
 		foreach ( $to_add as $value ) {
-			if ( ! add_metadata( $this->get_meta_type(), $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
+			if ( ! add_metadata( $meta_type, $object_id, wp_slash( $name ), wp_slash( $value ) ) ) {
 				return new WP_Error(
 					'rest_meta_database_error',
 					__( 'Could not update meta value in database.' ),
@@ -261,7 +262,8 @@
 	 * @return bool|WP_Error True if the meta field was updated, WP_Error otherwise.
 	 */
 	protected function update_meta_value( $object_id, $name, $value ) {
-		if ( ! current_user_can( 'edit_post_meta', $object_id, $name ) ) {
+		$meta_type = $this->get_meta_type();
+		if ( ! current_user_can(  "edit_{$meta_type}_meta", $object_id, $name ) ) {
 			return new WP_Error(
 				'rest_cannot_update',
 				sprintf( __( 'You do not have permission to edit the %s custom field.' ), $name ),
@@ -269,7 +271,6 @@
 			);
 		}
 
-		$meta_type  = $this->get_meta_type();
 		$meta_key   = wp_slash( $name );
 		$meta_value = wp_slash( $value );
 
