diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php
index 1dbf0c9867..d5502ea687 100644
--- a/src/wp-includes/post.php
+++ b/src/wp-includes/post.php
@@ -3158,8 +3158,17 @@ function wp_insert_post( $postarr, $wp_error = false ) {
 		}
 	}
 
-	// Don't allow contributors to set the post slug for pending review posts.
-	if ( 'pending' == $post_status && !current_user_can( 'publish_posts' ) ) {
+	/*
+	 * Don't allow contributors to set the post slug for pending review posts.
+	 *
+	 * For new posts check the primitive capability, for updates check the meta capability.
+	 */
+	$post_type_object = get_post_type_object( $post_type );
+
+	if (
+		( ! $update && 'pending' === $post_status && ! current_user_can( $post_type_object->cap->publish_posts ) ) OR
+		( $update && 'pending' === $post_status && ! current_user_can( 'publish_post', $post_ID ) )
+	) {
 		$post_name = '';
 	}
 
diff --git a/tests/phpunit/tests/post/wpInsertPost.php b/tests/phpunit/tests/post/wpInsertPost.php
index f0e150a8c8..b04e23c4d6 100644
--- a/tests/phpunit/tests/post/wpInsertPost.php
+++ b/tests/phpunit/tests/post/wpInsertPost.php
@@ -5,6 +5,41 @@
  */
 class Tests_WPInsertPost extends WP_UnitTestCase {
 
+	protected static $user_ids = array(
+		'administrator' => null,
+		'contributor'   => null,
+	);
+
+	static function wpSetUpBeforeClass( $factory ) {
+		self::$user_ids = array(
+			'administrator' => $factory->user->create( array( 'role' => 'administrator' ) ),
+			'contributor'   => $factory->user->create( array( 'role' => 'contributor' ) ),
+		);
+
+		$role = get_role( 'administrator' );
+		$role->add_cap( 'publish_mapped_meta_caps' );
+		$role->add_cap( 'publish_unmapped_meta_caps' );
+	}
+
+	function setUp() {
+		parent::setUp();
+
+		register_post_type( 'mapped_meta_caps', array(
+			'capability_type' => array( 'mapped_meta_cap', 'mapped_meta_caps' ),
+			'map_meta_cap'    => true,
+		) );
+
+		register_post_type( 'unmapped_meta_caps', array(
+			'capability_type' => array( 'unmapped_meta_cap', 'unmapped_meta_caps' ),
+			'map_meta_cap'    => false,
+		) );
+
+		register_post_type( 'no_admin_caps', array(
+			'capability_type' => array( 'no_admin_cap', 'no_admin_caps' ),
+			'map_meta_cap'    => false,
+		) );
+	}
+
 	/**
 	 * @ticket 11863
 	 */
@@ -89,4 +124,128 @@ class Tests_WPInsertPost extends WP_UnitTestCase {
 		$this->assertEquals( 'about', get_post( $another_about_page_id )->post_name );
 		$this->assertEquals( 'about-2', get_post( $about_page_id )->post_name );
 	}
+
+	/**
+	 * Data for testing the ability for users to set the post slug.
+	 *
+	 * @return array Array of test arguments.
+	 */
+	function data_various_post_types() {
+		/*
+		 * 1. Post type (see setUp).
+		 */
+		return array(
+			array( 'mapped_meta_caps' ),
+			array( 'unmapped_meta_caps' ),
+			array( 'post' ),
+		);
+	}
+
+	/**
+	 * Test contributor making changes to the pending post slug.
+	 *
+	 * @ticket 42464
+	 * @dataProvider data_various_post_types
+	 */
+	function test_contributor_setting_post_slug( $post_type ) {
+		wp_set_current_user( self::$user_ids['contributor'] );
+
+		$post_id = $this->factory()->post->create( array(
+			'post_title'   => 'Jefferson claim: nice to have Washington on your side.',
+			'post_content' => "I’m in the cabinet. I am complicit in watching him grabbin’ at power and kiss it.\n\nIf Washington isn’t gon’ listen to disciplined dissidents, this is the difference: this kid is out!",
+			'post_type'    => $post_type,
+			'post_name'    => 'new-washington',
+			'post_status'  => 'pending',
+		) );
+
+		$expected = '';
+		$actual = get_post_field( 'post_name', $post_id );
+
+		$this->assertEquals( $expected, $actual );
+
+		// Now update the post.
+		wp_update_post( array(
+			'ID' => $post_id,
+			'post_title' => 'Hamilton has Washington on side: Jefferson',
+			'post_name'  => 'edited-washington',
+		) );
+
+		$expected = '';
+		$actual = get_post_field( 'post_name', $post_id );
+
+		$this->assertEquals( $expected, $actual );
+	}
+
+	/**
+	 * Test administrator making changes to the pending post slug.
+	 *
+	 * @ticket 42464
+	 * @dataProvider data_various_post_types
+	 */
+	function test_administrator_setting_post_slug( $post_type ) {
+		wp_set_current_user( self::$user_ids['administrator'] );
+
+		$post_id = $this->factory()->post->create( array(
+			'post_title'   => 'What is the Conner Project?',
+			'post_content' => "Evan Hansen’s last link to his friend Conner is a signature on his broken arm.",
+			'post_type'    => $post_type,
+			'post_name'    => 'dear-evan-hansen-explainer',
+			'post_status'  => 'pending',
+		) );
+
+		$expected = 'dear-evan-hansen-explainer';
+		$actual = get_post_field( 'post_name', $post_id );
+
+		$this->assertEquals( $expected, $actual );
+
+		// Now update the post.
+		wp_update_post( array(
+			'ID' => $post_id,
+			'post_title' => 'Conner Project to close',
+			'post_name'  => 'dear-evan-hansen-spoiler',
+		) );
+
+		$expected = 'dear-evan-hansen-spoiler';
+		$actual = get_post_field( 'post_name', $post_id );
+
+		$this->assertEquals( $expected, $actual );
+	}
+
+	/**
+	 * Test administrator making changes tp a pending post slug for a post type they don't
+	 * have permission to publish.
+	 *
+	 * These assertions failed prior to ticket #42464.
+	 *
+	 * @ticket 42464
+	 */
+	function test_administrator_not_permitted_setting_post_slug() {
+		wp_set_current_user( self::$user_ids['administrator'] );
+
+		$post_id = $this->factory()->post->create( array(
+			'post_title'   => 'Everything is legal in New Jersey',
+			'post_content' => 'Shortly before his death, Philip Hamilton was heard to claim everything was legal in the garden state.',
+			'post_type'    => 'no_admin_caps',
+			'post_name'    => 'yet-another-duel',
+			'post_status'  => 'pending',
+		) );
+
+		$expected = '';
+		$actual = get_post_field( 'post_name', $post_id );
+
+		$this->assertEquals( $expected, $actual );
+
+		// Now update the post.
+		wp_update_post( array(
+			'ID' => $post_id,
+			'post_title' => 'Ten things illegal in New Jersey',
+			'post_name'  => 'foreshadowing-in-nj',
+		) );
+
+		$expected = '';
+		$actual = get_post_field( 'post_name', $post_id );
+
+		$this->assertEquals( $expected, $actual );
+	}
+
 }
