Index: wp-includes/js/media-models.js
===================================================================
--- wp-includes/js/media-models.js	(revision 23009)
+++ wp-includes/js/media-models.js	(working copy)
@@ -233,7 +233,7 @@
 
 			// Overload the `update` request so properties can be saved.
 			} else if ( 'update' === method ) {
-				if ( ! this.get('nonces') )
+				if ( ! this.get('nonces') || ! this.get('nonces').update )
 					return $.Deferred().resolveWith( this ).promise();
 
 				options = options || {};
@@ -286,6 +286,9 @@
 		saveCompat: function( data, options ) {
 			var model = this;
 
+			if ( ! this.get('nonces') || ! this.get('nonces').update )
+				return $.Deferred().resolveWith( this ).promise();
+
 			return media.post( 'save-attachment-compat', _.defaults({
 				id:      this.id,
 				nonce:   this.get('nonces').update,
Index: wp-includes/media.php
===================================================================
--- wp-includes/media.php	(revision 23011)
+++ wp-includes/media.php	(working copy)
@@ -1334,11 +1334,17 @@
 		'icon'        => wp_mime_type_icon( $attachment->ID ),
 		'dateFormatted' => mysql2date( get_option('date_format'), $attachment->post_date ),
 		'nonces'      => array(
-			'update' => wp_create_nonce( 'update-post_' . $attachment->ID ),
-			'delete' => wp_create_nonce( 'delete-post_' . $attachment->ID ),
+			'update' => false,
+			'delete' => false,
 		),
 	);
 
+	if ( current_user_can( 'edit_post', $attachment->ID ) )
+		$response['nonces']['update'] = wp_create_nonce( 'update-post_' . $attachment->ID );
+
+	if ( current_user_can( 'delete_post', $attachment->ID ) )
+		$response['nonces']['delete'] = wp_create_nonce( 'delete-post_' . $attachment->ID );
+
 	if ( $meta && 'image' === $type ) {
 		$sizes = array();
 		$possible_sizes = apply_filters( 'image_size_names_choose', array(
@@ -1690,7 +1696,7 @@
 				<# if ( 'image' === data.type && ! data.uploading && data.width && data.height ) { #>
 					<div class="dimensions">{{ data.width }} &times; {{ data.height }}</div>
 				<# } #>
-				<# if ( ! data.uploading ) { #>
+				<# if ( ! data.uploading && data.nonces['delete'] ) { #>
 					<div class="delete-attachment">
 						<a href="#"><?php _e( 'Delete Permanently' ); ?></a>
 					</div>
Index: wp-admin/includes/ajax-actions.php
===================================================================
--- wp-admin/includes/ajax-actions.php	(revision 23009)
+++ wp-admin/includes/ajax-actions.php	(working copy)
@@ -1812,9 +1812,15 @@
 	if ( ! $id = absint( $_REQUEST['id'] ) )
 		wp_send_json_error();
 
-	if ( ! current_user_can( 'read_post', $id ) )
+	if ( ! $post = get_post( $id ) )
 		wp_send_json_error();
 
+	if ( 'attachment' != $post->post_type )
+		wp_send_json_error();
+
+	if ( ! current_user_can( 'upload_files' ) )
+		wp_send_json_error();
+
 	if ( ! $attachment = wp_prepare_attachment_for_js( $id ) )
 		wp_send_json_error();
 
@@ -1827,6 +1833,9 @@
  * @since 3.5.0
  */
 function wp_ajax_query_attachments() {
+	if ( ! current_user_can( 'upload_files' ) )
+		wp_send_json_error();
+
 	$query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array();
 	$query = array_intersect_key( $query, array_flip( array(
 		's', 'order', 'orderby', 'posts_per_page', 'paged', 'post_mime_type',
@@ -1988,15 +1997,14 @@
 	if ( ! $post = get_post( $id ) )
 		wp_send_json_error();
 
-	if ( ! current_user_can( 'edit_post', $id ) )
-		wp_send_json_error();
-
 	if ( 'attachment' != $post->post_type )
 		wp_send_json_error();
 
-	// If this attachment is unattached, attach it. Primarily a back compat thing.
-	if ( 0 == $post->post_parent && $insert_into_post_id = intval( $_POST['post_id'] ) ) {
-		wp_update_post( array( 'ID' => $id, 'post_parent' => $insert_into_post_id ) );
+	if ( current_user_can( 'edit_post', $id ) ) {
+		// If this attachment is unattached, attach it. Primarily a back compat thing.
+		if ( 0 == $post->post_parent && $insert_into_post_id = intval( $_POST['post_id'] ) ) {
+			wp_update_post( array( 'ID' => $id, 'post_parent' => $insert_into_post_id ) );
+		}
 	}
 
 	$rel = $url = '';
