diff --git a/src/js/_enqueues/wp/embed.js b/src/js/_enqueues/wp/embed.js
index fa2934f379..58ae034f49 100644
--- a/src/js/_enqueues/wp/embed.js
+++ b/src/js/_enqueues/wp/embed.js
@@ -49,6 +49,7 @@
 
 		var iframes = document.querySelectorAll( 'iframe[data-secret="' + data.secret + '"]' ),
 			blockquotes = document.querySelectorAll( 'blockquote[data-secret="' + data.secret + '"]' ),
+			allowedProtocols = new RegExp( '^https?:$', 'i' ),
 			i, source, height, sourceURL, targetURL;
 
 		for ( i = 0; i < blockquotes.length; i++ ) {
@@ -84,6 +85,11 @@
 				sourceURL.href = source.getAttribute( 'src' );
 				targetURL.href = data.value;
 
+				/* Only follow link if the protocol is in the allow list. */
+				if ( ! allowedProtocols.test( targetURL.protocol ) ) {
+					continue;
+				}
+
 				/* Only continue if link hostname matches iframe's hostname. */
 				if ( targetURL.host === sourceURL.host ) {
 					if ( document.activeElement === source ) {
diff --git a/src/js/media/views/frame/video-details.js b/src/js/media/views/frame/video-details.js
index 2dbb22f774..6a0d604202 100644
--- a/src/js/media/views/frame/video-details.js
+++ b/src/js/media/views/frame/video-details.js
@@ -106,6 +106,7 @@ VideoDetails = MediaDetails.extend(/** @lends wp.media.view.MediaFrame.VideoDeta
 
 			wp.ajax.send( 'set-attachment-thumbnail', {
 				data : {
+					_ajax_nonce: wp.media.view.settings.nonce.setAttachmentThumbnail,
 					urls: urls,
 					thumbnail_id: attachment.get( 'id' )
 				}
diff --git a/src/wp-admin/about.php b/src/wp-admin/about.php
index 96dd83c22c..2907251717 100644
--- a/src/wp-admin/about.php
+++ b/src/wp-admin/about.php
@@ -45,6 +45,26 @@ require_once ABSPATH . 'wp-admin/admin-header.php';
 		<div class="about__section changelog">
 			<div class="column">
 				<h2><?php _e( 'Maintenance and Security Releases' ); ?></h2>
+				<p>
+					<?php
+					printf(
+						__( '<strong>Version %s</strong> addressed some security issues.' ),
+						'6.1.2'
+					);
+					?>
+					<?php
+					printf(
+						/* translators: %s: HelpHub URL. */
+						__( 'For more information, see <a href="%s">the release notes</a>.' ),
+						sprintf(
+							/* translators: %s: WordPress version. */
+							esc_url( __( 'https://wordpress.org/support/wordpress-version/version-%s/' ) ),
+							sanitize_title( '6.1.2' )
+						)
+					);
+					?>
+				</p>
+
 				<p>
 					<?php
 					printf(
diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php
index 6ca6a0217a..4af19ff6bb 100644
--- a/src/wp-admin/includes/ajax-actions.php
+++ b/src/wp-admin/includes/ajax-actions.php
@@ -2771,6 +2771,10 @@ function wp_ajax_set_attachment_thumbnail() {
 		wp_send_json_error();
 	}
 
+	if ( false === check_ajax_referer( 'set-attachment-thumbnail', '_ajax_nonce', false ) ) {
+		wp_send_json_error();
+	}
+
 	$post_ids = array();
 	// For each URL, try to find its corresponding post ID.
 	foreach ( $_POST['urls'] as $url ) {
diff --git a/src/wp-includes/block-template.php b/src/wp-includes/block-template.php
index 19f3b5fb14..2f2c7ad1d0 100644
--- a/src/wp-includes/block-template.php
+++ b/src/wp-includes/block-template.php
@@ -240,9 +240,7 @@ function get_the_block_template_html() {
 	$content = do_blocks( $content );
 	$content = wptexturize( $content );
 	$content = convert_smilies( $content );
-	$content = shortcode_unautop( $content );
 	$content = wp_filter_content_tags( $content );
-	$content = do_shortcode( $content );
 	$content = str_replace( ']]>', ']]&gt;', $content );
 
 	// Wrap block template in .wp-site-blocks to allow for specific descendant styles
diff --git a/src/wp-includes/blocks.php b/src/wp-includes/blocks.php
index 29e375ab89..3327ea0b02 100644
--- a/src/wp-includes/blocks.php
+++ b/src/wp-includes/blocks.php
@@ -794,6 +794,10 @@ function serialize_blocks( $blocks ) {
 function filter_block_content( $text, $allowed_html = 'post', $allowed_protocols = array() ) {
 	$result = '';
 
+	if ( false !== strpos( $text, '<!--' ) && false !== strpos( $text, '--->' ) ) {
+		$text = preg_replace_callback( '%<!--(.*?)--->%', '_filter_block_content_callback', $text );
+	}
+
 	$blocks = parse_blocks( $text );
 	foreach ( $blocks as $block ) {
 		$block   = filter_block_kses( $block, $allowed_html, $allowed_protocols );
@@ -803,6 +807,19 @@ function filter_block_content( $text, $allowed_html = 'post', $allowed_protocols
 	return $result;
 }
 
+/**
+ * Callback used for regular expression replacement in filter_block_content().
+ *
+ * @private
+ * @since 6.2.1
+ *
+ * @param array $matches Array of preg_replace_callback matches.
+ * @return string Replacement string.
+ */
+function _filter_block_content_callback( $matches ) {
+	return '<!--' . rtrim( $matches[1], '-' ) . '-->';
+}
+
 /**
  * Filters and sanitizes a parsed block to remove non-allowable HTML
  * from block attribute values.
diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php
index 2866bfce17..95f62c5d6b 100644
--- a/src/wp-includes/formatting.php
+++ b/src/wp-includes/formatting.php
@@ -2432,6 +2432,29 @@ function sanitize_html_class( $class, $fallback = '' ) {
 	return apply_filters( 'sanitize_html_class', $sanitized, $class, $fallback );
 }
 
+/**
+ * Strips out all characters not allowed in a locale name.
+ *
+ * @since 6.2.1
+ *
+ * @param string $locale_name The locale name to be sanitized.
+ * @return string The sanitized value.
+ */
+function sanitize_locale_name( $locale_name ) {
+	// Limit to A-Z, a-z, 0-9, '_', '-'.
+	$sanitized = preg_replace( '/[^A-Za-z0-9_-]/', '', $locale_name );
+
+	/**
+	 * Filters a sanitized locale name string.
+	 *
+	 * @since 6.2.1
+	 *
+	 * @param string $sanitized   The sanitized locale name.
+	 * @param string $locale_name The locale name before sanitization.
+	 */
+	return apply_filters( 'sanitize_locale_name', $sanitized, $locale_name );
+}
+
 /**
  * Converts lone & characters into `&#038;` (a.k.a. `&amp;`)
  *
diff --git a/src/wp-includes/l10n.php b/src/wp-includes/l10n.php
index c5148a02e8..331ea1d8f3 100644
--- a/src/wp-includes/l10n.php
+++ b/src/wp-includes/l10n.php
@@ -149,9 +149,9 @@ function determine_locale() {
 	$wp_lang = '';
 
 	if ( ! empty( $_GET['wp_lang'] ) ) {
-		$wp_lang = sanitize_text_field( $_GET['wp_lang'] );
+		$wp_lang = sanitize_locale_name( wp_unslash( $_GET['wp_lang'] ) );
 	} elseif ( ! empty( $_COOKIE['wp_lang'] ) ) {
-		$wp_lang = sanitize_text_field( $_COOKIE['wp_lang'] );
+		$wp_lang = sanitize_locale_name( wp_unslash( $_COOKIE['wp_lang'] ) );
 	}
 
 	if ( ! empty( $wp_lang ) && ! empty( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'] ) {
diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php
index 804a34f6ac..0b05552e7a 100644
--- a/src/wp-includes/media.php
+++ b/src/wp-includes/media.php
@@ -4516,7 +4516,8 @@ function wp_enqueue_media( $args = array() ) {
 		/** This filter is documented in wp-admin/includes/media.php */
 		'captions'          => ! apply_filters( 'disable_captions', '' ),
 		'nonce'             => array(
-			'sendToEditor' => wp_create_nonce( 'media-send-to-editor' ),
+			'sendToEditor'           => wp_create_nonce( 'media-send-to-editor' ),
+			'setAttachmentThumbnail' => wp_create_nonce( 'set-attachment-thumbnail' ),
 		),
 		'post'              => array(
 			'id' => 0,
diff --git a/src/wp-includes/version.php b/src/wp-includes/version.php
index b6a5b45572..9c53216ef3 100644
--- a/src/wp-includes/version.php
+++ b/src/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '6.1.2-alpha-54847-src';
+$wp_version = '6.1.2-src';
 
 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
diff --git a/tests/phpunit/tests/ajax/Attachments.php b/tests/phpunit/tests/ajax/Attachments.php
index 91d6943c99..b294c32170 100644
--- a/tests/phpunit/tests/ajax/Attachments.php
+++ b/tests/phpunit/tests/ajax/Attachments.php
@@ -103,4 +103,95 @@ class Tests_Ajax_Attachments extends WP_Ajax_UnitTestCase {
 		$this->assertTrue( $response['success'] );
 		$this->assertSame( $expected, $response['data'] );
 	}
+
+	public function test_wp_ajax_set_attachment_thumbnail_success() {
+		// Become an administrator.
+		$post    = $_POST;
+		$user_id = self::factory()->user->create(
+			array(
+				'role'       => 'administrator',
+				'user_login' => 'user_36578_administrator',
+				'user_email' => 'user_36578_administrator@example.com',
+			)
+		);
+		wp_set_current_user( $user_id );
+		$_POST = array_merge( $_POST, $post );
+
+		// Upload the attachment itself.
+		$filename = DIR_TESTDATA . '/uploads/small-audio.mp3';
+		$contents = file_get_contents( $filename );
+
+		$upload     = wp_upload_bits( wp_basename( $filename ), null, $contents );
+		$attachment = $this->_make_attachment( $upload );
+
+		// Upload the thumbnail.
+		$filename = DIR_TESTDATA . '/images/waffles.jpg';
+		$contents = file_get_contents( $filename );
+
+		$upload    = wp_upload_bits( wp_basename( $filename ), null, $contents );
+		$thumbnail = $this->_make_attachment( $upload );
+
+		// Set up a default request.
+		$_POST['_ajax_nonce']  = wp_create_nonce( 'set-attachment-thumbnail' );
+		$_POST['thumbnail_id'] = $thumbnail;
+		$_POST['urls']         = array( wp_get_attachment_url( $attachment ) );
+
+		// Make the request.
+		try {
+			$this->_handleAjax( 'set-attachment-thumbnail' );
+		} catch ( WPAjaxDieContinueException $e ) {
+			unset( $e );
+		}
+
+		// Get the response.
+		$response = json_decode( $this->_last_response, true );
+
+		// Ensure everything is correct.
+		$this->assertTrue( $response['success'] );
+	}
+
+	public function test_wp_ajax_set_attachment_thumbnail_missing_nonce() {
+		// Become an administrator.
+		$post    = $_POST;
+		$user_id = self::factory()->user->create(
+			array(
+				'role'       => 'administrator',
+				'user_login' => 'user_36578_administrator',
+				'user_email' => 'user_36578_administrator@example.com',
+			)
+		);
+		wp_set_current_user( $user_id );
+		$_POST = array_merge( $_POST, $post );
+
+		// Upload the attachment itself.
+		$filename = DIR_TESTDATA . '/uploads/small-audio.mp3';
+		$contents = file_get_contents( $filename );
+
+		$upload     = wp_upload_bits( wp_basename( $filename ), null, $contents );
+		$attachment = $this->_make_attachment( $upload );
+
+		// Upload the thumbnail.
+		$filename = DIR_TESTDATA . '/images/waffles.jpg';
+		$contents = file_get_contents( $filename );
+
+		$upload    = wp_upload_bits( wp_basename( $filename ), null, $contents );
+		$thumbnail = $this->_make_attachment( $upload );
+
+		// Set up a default request.
+		$_POST['thumbnail_id'] = $thumbnail;
+		$_POST['urls']         = array( wp_get_attachment_url( $attachment ) );
+
+		// Make the request.
+		try {
+			$this->_handleAjax( 'set-attachment-thumbnail' );
+		} catch ( WPAjaxDieContinueException $e ) {
+			unset( $e );
+		}
+
+		// Get the response.
+		$response = json_decode( $this->_last_response, true );
+
+		// Check that success is false without sending nonce.
+		$this->assertFalse( $response['success'] );
+	}
 }
diff --git a/tests/phpunit/tests/formatting/sanitizeLocaleName.php b/tests/phpunit/tests/formatting/sanitizeLocaleName.php
new file mode 100644
index 0000000000..cd22acbf2c
--- /dev/null
+++ b/tests/phpunit/tests/formatting/sanitizeLocaleName.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @group formatting
+ *
+ * @covers ::sanitize_locale_name
+ */
+class Tests_Formatting_SanitizeLocaleName extends WP_UnitTestCase {
+	/**
+	 * @dataProvider data_sanitize_locale_name_returns_non_empty_string
+	 */
+	public function test_sanitize_locale_name_returns_non_empty_string( $expected, $input ) {
+		$this->assertSame( $expected, sanitize_locale_name( $input ) );
+	}
+
+	public function data_sanitize_locale_name_returns_non_empty_string() {
+		return array(
+			// array( expected, input )
+			array( 'en_US', 'en_US' ),
+			array( 'en', 'en' ),
+			array( 'fr_FR', 'fr_FR' ),
+			array( 'fr_FR', 'fr_FR' ),
+			array( 'fr_FR-e2791ba830489d23043be8650a22a22b', 'fr_FR-e2791ba830489d23043be8650a22a22b' ),
+			array( '-fr_FRmo', '-fr_FR.mo' ),
+			array( '12324', '$12324' ),
+			array( '4124FRRa', '/4124$$$%%FRRa' ),
+			array( 'FR', '<FR' ),
+			array( 'FR_FR', 'FR_FR' ),
+			array( '--__', '--__' ),
+		);
+	}
+
+	/**
+	 * @dataProvider data_sanitize_locale_name_returns_empty_string
+	 */
+	public function test_sanitize_locale_name_returns_empty_string( $input ) {
+		$this->assertSame( '', sanitize_locale_name( $input ) );
+	}
+
+	public function data_sanitize_locale_name_returns_empty_string() {
+		return array(
+			// array( input )
+			array( '$<>' ),
+			array( '/$$$%%\\)' ),
+			array( '....' ),
+			array( '@///' ),
+		);
+	}
+}