Index: src/wp-admin/js/theme-plugin-editor.js
===================================================================
--- src/wp-admin/js/theme-plugin-editor.js	(revision 41874)
+++ src/wp-admin/js/theme-plugin-editor.js	(working copy)
@@ -51,9 +51,7 @@
 		component.warning = $( '.file-editor-warning' );
 
 		if ( component.warning.length > 0 ) {
-			$( 'body' ).addClass( 'modal-open' );
-			component.warning.find( '.file-editor-warning-go-back' ).focus();
-			component.warning.on( 'click', '.file-editor-warning-dismiss', component.dismissWarning );
+			component.showWarning();
 		}
 
 		if ( false !== component.codeEditor ) {
@@ -78,6 +76,62 @@
 	};
 
 	/**
+	 * Set up and display the warning modal.
+	 *
+	 * @since 4.9.0
+	 * @returns {void}
+	 */
+	component.showWarning = function() {
+		// Get the text within the modal.
+		var rawMessage = component.warning.find( '.file-editor-warning-message' ).text();
+		// Hide all the #wpwrap content from assistive technologies.
+		$( '#wpwrap' ).attr( 'aria-hidden', 'true' );
+		// Detach the warning modal from its position and append it to the body.
+		$( document.body )
+			.addClass( 'modal-open' )
+			.append( component.warning.detach() );
+		// Reveal the modal and set focus on the go back button.
+		component.warning
+			.removeClass( 'hidden' )
+			.find( '.file-editor-warning-go-back' ).focus();
+		// Get the links and buttons within the modal.
+		component.warningTabbables = component.warning.find( 'a, button' );
+		// Attach event handlers.
+		component.warningTabbables.on( 'keydown', component.constrainTabbing );
+		component.warning.on( 'click', '.file-editor-warning-dismiss', component.dismissWarning );
+		// Make screen readers announce the warning message after a short delay (necessary for some screen readers).
+		setTimeout( function() {
+			wp.a11y.speak( wp.sanitize.stripTags( rawMessage.replace( /\s+/g, ' ' ) ), 'assertive' );
+		}, 1000 );
+	};
+
+	/**
+	 * Constrain tabbing within the warning modal.
+	 *
+	 * @since 4.9.0
+	 * @param {object} event jQuery event object.
+	 * @returns {void}
+	 */
+	component.constrainTabbing = function( event ) {
+		var firstTabbable, lastTabbable;
+
+		if ( 9 !== event.which ) {
+			return;
+		}
+
+		firstTabbable = component.warningTabbables.first()[0];
+		lastTabbable = component.warningTabbables.last()[0];
+
+		if ( lastTabbable === event.target && ! event.shiftKey ) {
+			firstTabbable.focus();
+			event.preventDefault();
+		} else if ( firstTabbable === event.target && event.shiftKey ) {
+			lastTabbable.focus();
+			event.preventDefault();
+		}
+	};
+
+	/**
 	 * Dismiss the warning modal.
 	 *
 	 * @since 4.9.0
@@ -91,10 +145,8 @@
 
 		// Hide modal.
 		component.warning.remove();
+		$( '#wpwrap' ).removeAttr( 'aria-hidden' );
 		$( 'body' ).removeClass( 'modal-open' );
-
-		// Return focus - is this a trap?
-		component.instance.codemirror.focus();
 	};
 
 	/**
Index: src/wp-admin/plugin-editor.php
===================================================================
--- src/wp-admin/plugin-editor.php	(revision 41874)
+++ src/wp-admin/plugin-editor.php	(working copy)
@@ -292,13 +292,15 @@
 		$return_url = admin_url( '/' );
 	}
 ?>
-<div id="file-editor-warning" class="notification-dialog-wrap file-editor-warning hide-if-no-js">
+<div id="file-editor-warning" class="notification-dialog-wrap file-editor-warning hide-if-no-js hidden">
 	<div class="notification-dialog-background"></div>
-	<div class="notification-dialog" role="dialog" aria-labelledby="file-editor-warning-title" tabindex="0">
+	<div class="notification-dialog">
 		<div class="file-editor-warning-content">
-			<h1 id="file-editor-warning-title"><?php _e( 'Heads up!' ); ?></h1>
-			<p><?php _e( 'You appear to be making direct edits to your plugin in the WordPress dashboard. We recommend that you don&#8217;t! Editing plugins directly may introduce incompatibilities that break your theme or other plugins, and can leave you unable to log back in to WordPress and undo changes.' ); ?></p>
-			<p><?php _e( 'If you absolutely have to edit this plugin, create a copy with a new name and hang on to the original version, so you can re-enable a functional version if something goes wrong.' ); ?></p>
+			<div class="file-editor-warning-message">
+				<h1><?php _e( 'Heads up!' ); ?></h1>
+				<p><?php _e( 'You appear to be making direct edits to your plugin in the WordPress dashboard. We recommend that you don&#8217;t! Editing plugins directly may introduce incompatibilities that break your theme or other plugins, and can leave you unable to log back in to WordPress and undo changes.' ); ?></p>
+				<p><?php _e( 'If you absolutely have to edit this plugin, create a copy with a new name and hang on to the original version, so you can re-enable a functional version if something goes wrong.' ); ?></p>
+			</div>
 			<p>
 				<a class="button file-editor-warning-go-back" href="<?php echo esc_url( $return_url ); ?>"><?php _e( 'Go back' ); ?></a>
 				<button type="button" class="file-editor-warning-dismiss button button-primary"><?php _e( 'I understand' ); ?></button>
Index: src/wp-admin/theme-editor.php
===================================================================
--- src/wp-admin/theme-editor.php	(revision 41874)
+++ src/wp-admin/theme-editor.php	(working copy)
@@ -297,22 +297,24 @@
 		$return_url = admin_url( '/' );
 	}
 ?>
-<div id="file-editor-warning" class="notification-dialog-wrap file-editor-warning hide-if-no-js">
+<div id="file-editor-warning" class="notification-dialog-wrap file-editor-warning hide-if-no-js hidden">
 	<div class="notification-dialog-background"></div>
-	<div class="notification-dialog" role="dialog" aria-labelledby="file-editor-warning-title" tabindex="0">
+	<div class="notification-dialog">
 		<div class="file-editor-warning-content">
-			<h1 id="file-editor-warning-title"><?php _e( 'Heads up!' ); ?></h1>
+			<div class="file-editor-warning-message">
+				<h1><?php _e( 'Heads up!' ); ?></h1>
+				<p>
+					<?php
+					echo sprintf(
+						/* translators: %s is a link to Custom CSS section in the Customizer. */
+						__( 'You appear to be making direct edits to your theme in the WordPress dashboard. We recommend that you don&#8217;t! Editing this code directly is dangerous, and can leave you unable to log back in to WordPress and undo changes. There&#8217;s no need to change your CSS here &mdash; you can edit and live preview CSS changes in WordPress&#8217;s <a href="%s">built in CSS editor</a>.' ),
+						esc_url( add_query_arg( 'autofocus[section]', 'custom_css', admin_url( 'customize.php' ) ) )
+					);
+					?>
+				</p>
+				<p><?php _e( 'If you decide to go ahead with direct edits anyway, make sure to back up all your site&#8217;s files before making changes so you can restore a functional version if something goes wrong.' ); ?></p>
+			</div>
 			<p>
-				<?php
-				echo sprintf(
-					/* translators: %s is a link to Custom CSS section in the Customizer. */
-					__( 'You appear to be making direct edits to your theme in the WordPress dashboard. We recommend that you don&#8217;t! Editing this code directly is dangerous, and can leave you unable to log back in to WordPress and undo changes. There&#8217;s no need to change your CSS here &mdash; you can edit and live preview CSS changes in WordPress&#8217;s <a href="%s">built in CSS editor</a>.' ),
-					esc_url( add_query_arg( 'autofocus[section]', 'custom_css', admin_url( 'customize.php' ) ) )
-				);
-				?>
-			</p>
-			<p><?php _e( 'If you decide to go ahead with direct edits anyway, make sure to back up all your site&#8217;s files before making changes so you can restore a functional version if something goes wrong.' ); ?></p>
-			<p>
 				<a class="button file-editor-warning-go-back" href="<?php echo esc_url( $return_url ); ?>"><?php _e( 'Go back' ); ?></a>
 				<button type="button" class="file-editor-warning-dismiss button button-primary"><?php _e( 'I understand' ); ?></button>
 			</p>
Index: src/wp-includes/script-loader.php
===================================================================
--- src/wp-includes/script-loader.php	(revision 41874)
+++ src/wp-includes/script-loader.php	(working copy)
@@ -469,7 +469,7 @@
 	$scripts->add( 'htmlhint', '/wp-includes/js/codemirror/htmlhint.js', array(), '0.9.14-xwp' );
 	$scripts->add( 'htmlhint-kses', '/wp-includes/js/codemirror/htmlhint-kses.js', array( 'htmlhint' ) );
 	$scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'wp-codemirror' ) );
-	$scripts->add( 'wp-theme-plugin-editor', "/wp-admin/js/theme-plugin-editor$suffix.js", array( 'wp-util', 'jquery', 'jquery-ui-core', 'wp-a11y', 'underscore' ) );
+	$scripts->add( 'wp-theme-plugin-editor', "/wp-admin/js/theme-plugin-editor$suffix.js", array( 'wp-util', 'wp-sanitize', 'jquery', 'jquery-ui-core', 'wp-a11y', 'underscore' ) );
 	did_action( 'init' ) && $scripts->add_inline_script( 'wp-theme-plugin-editor', sprintf( 'wp.themePluginEditor.l10n = %s;', wp_json_encode( array(
 		'saveAlert' => __( 'The changes you made will be lost if you navigate away from this page.' ),
 		'saveError' => __( 'Something went wrong. Your change may not have been saved. Please try again. There is also a chance that you may need to manually fix and upload the file over FTP.' ),
