Index: src/wp-includes/capabilities.php
===================================================================
--- src/wp-includes/capabilities.php	(revision 41309)
+++ src/wp-includes/capabilities.php	(working copy)
@@ -440,9 +440,6 @@
 		else
 			$caps[] = 'do_not_allow';
 		break;
-	case 'customize' :
-		$caps[] = 'edit_theme_options';
-		break;
 	case 'delete_site':
 		if ( is_multisite() ) {
 			$caps[] = 'manage_options';
@@ -862,3 +859,44 @@
 
 	return $allcaps;
 }
+
+/**
+ * Filters the user capabilities to grant the 'customize' capability as necessary.
+ *
+ * A user must have the 'edit_theme_options' capability for it to be granted.
+ *
+ * @since 4.9.0
+ *
+ * @param array $allcaps An array of all the user's capabilities.
+ * @return array Filtered array of the user's capabilities.
+ */
+function wp_maybe_grant_customize_cap( $allcaps ) {
+	if ( ! empty( $allcaps['edit_theme_options'] ) ) {
+		$allcaps['customize'] = true;
+	}
+
+	return $allcaps;
+}
+
+/**
+ * Filters the user capabilities to grant customize changeset capabilities as necessary.
+ *
+ * The capabilities are granted based on whether the user can 'customize'.
+ *
+ * @since 4.9.0
+ *
+ * @param array $allcaps An array of all the user's capabilities.
+ * @return array Filtered array of the user's capabilities.
+ */
+function wp_maybe_grant_customize_changesets_caps( $allcaps ) {
+	if ( ! empty( $allcaps['customize'] ) ) {
+		$post_type = get_post_type_object( 'customize_changeset' );
+		foreach ( get_object_vars( $post_type->cap ) as $post_cap => $changeset_cap ) {
+			if ( '_posts' === substr( $post_cap, -6 ) ) {
+				$allcaps[ $changeset_cap ] = true;
+			}
+		}
+	}
+
+	return $allcaps;
+}
Index: src/wp-includes/default-filters.php
===================================================================
--- src/wp-includes/default-filters.php	(revision 41309)
+++ src/wp-includes/default-filters.php	(working copy)
@@ -514,5 +514,7 @@
 
 // Capabilities
 add_filter( 'user_has_cap', 'wp_maybe_grant_install_languages_cap', 1 );
+add_filter( 'user_has_cap', 'wp_maybe_grant_customize_cap', 1 );
+add_filter( 'user_has_cap', 'wp_maybe_grant_customize_changesets_caps', 10 );
 
 unset( $filter, $action );
Index: src/wp-includes/post.php
===================================================================
--- src/wp-includes/post.php	(revision 41309)
+++ src/wp-includes/post.php	(working copy)
@@ -176,23 +176,6 @@
 		'delete_with_user' => false,
 		'supports' => array( 'title', 'author' ),
 		'capability_type' => 'customize_changeset',
-		'capabilities' => array(
-			'create_posts' => 'customize',
-			'delete_others_posts' => 'customize',
-			'delete_post' => 'customize',
-			'delete_posts' => 'customize',
-			'delete_private_posts' => 'customize',
-			'delete_published_posts' => 'customize',
-			'edit_others_posts' => 'customize',
-			'edit_post' => 'customize',
-			'edit_posts' => 'customize',
-			'edit_private_posts' => 'customize',
-			'edit_published_posts' => 'do_not_allow',
-			'publish_posts' => 'customize',
-			'read' => 'read',
-			'read_post' => 'customize',
-			'read_private_posts' => 'customize',
-		),
 	) );
 
 	register_post_status( 'publish', array(
@@ -2964,7 +2947,7 @@
  *     @type string $guid                  Global Unique ID for referencing the post. Default empty.
  *     @type array  $post_category         Array of category names, slugs, or IDs.
  *                                         Defaults to value of the 'default_category' option.
- *     @type array  $tags_input            Array of tag names, slugs, or IDs. Default empty. 
+ *     @type array  $tags_input            Array of tag names, slugs, or IDs. Default empty.
  *     @type array  $tax_input             Array of taxonomy terms keyed by their taxonomy name. Default empty.
  *     @type array  $meta_input            Array of post meta values keyed by their post meta key. Default empty.
  * }
