Index: src/wp-admin/admin-ajax.php
===================================================================
--- src/wp-admin/admin-ajax.php	(revision 41769)
+++ src/wp-admin/admin-ajax.php	(working copy)
@@ -65,6 +65,7 @@
 	'generate-password', 'save-wporg-username', 'delete-plugin', 'search-plugins',
 	'search-install-plugins', 'activate-plugin', 'update-theme', 'delete-theme', 'install-theme',
 	'get-post-thumbnail-html', 'get-community-events', 'edit-theme-plugin-file',
+	'edit-theme-plugin-warning-dismissed',
 );
 
 // Deprecated
Index: src/wp-admin/css/common.css
===================================================================
--- src/wp-admin/css/common.css	(revision 41769)
+++ src/wp-admin/css/common.css	(working copy)
@@ -3147,6 +3147,10 @@
 	line-height: 180%;
 }
 
+#file-editor-warning .file-editor-warning-content {
+	margin: 25px;
+}
+
 /* @todo: can we use a common class for these? */
 .nav-menus-php .item-edit:before,
 .widget-top .widget-action .toggle-indicator:before,
Index: src/wp-admin/includes/ajax-actions.php
===================================================================
--- src/wp-admin/includes/ajax-actions.php	(revision 41769)
+++ src/wp-admin/includes/ajax-actions.php	(working copy)
@@ -3989,3 +3989,15 @@
 		) );
 	}
 }
+
+/**
+ * Update user meta when a user dismisses the 'Heads Up' warning modal displayed when using
+ * the plugin or theme editor for the first time.
+ */
+function wp_ajax_edit_theme_plugin_warning_dismissed() {
+	check_ajax_referer( 'dismiss-notice' );
+
+	$dismissed = isset( $_POST['dismissed'] ) ? sanitize_text_field( $_POST['dismissed'] ) : 'themes';
+	update_user_meta( get_current_user_id(), 'hide_' .  $dismissed . '_editor_notice', true );
+	wp_die( 1 );
+}
Index: src/wp-admin/js/theme-plugin-editor.js
===================================================================
--- src/wp-admin/js/theme-plugin-editor.js	(revision 41769)
+++ src/wp-admin/js/theme-plugin-editor.js	(working copy)
@@ -46,7 +46,15 @@
 		component.form.on( 'submit', component.submit );
 		component.textarea = component.form.find( '#newcontent' );
 		component.textarea.on( 'change', component.onChange );
+		component.warning = $( '.file-editor-warning' );
 
+		if ( component.warning.length > 0 ) {
+			$( 'body' ).addClass( 'modal-open' );
+			component.warning.find( '.notice-dismiss' ).focus();
+			component.warning.on( 'click', '.notice-dismiss', component.dismissWarning );
+		};
+
+
 		if ( false !== component.codeEditor ) {
 			/*
 			 * Defer adding notices until after DOM ready as workaround for WP Admin injecting
@@ -67,6 +75,25 @@
 	};
 
 	/**
+	 * Dismiss the warning modal.
+	 */
+	component.dismissWarning = function() {
+
+		// update user meta
+		var request = wp.ajax.post( 'edit-theme-plugin-warning-dismissed', {
+			_ajax_nonce: wp.themePluginEditor.nonce,
+			dismissed:   wp.themePluginEditor.themeOrPlugin
+		} );
+
+		// hide modal
+		component.warning.remove();
+		$( 'body' ).removeClass( 'modal-open' );
+
+		// return focus - is this a trap?
+		component.instance.codemirror.focus();
+	}
+
+	/**
 	 * Callback for when a change happens.
 	 *
 	 * @since 4.9.0
Index: src/wp-admin/plugin-editor.php
===================================================================
--- src/wp-admin/plugin-editor.php	(revision 41769)
+++ src/wp-admin/plugin-editor.php	(working copy)
@@ -142,6 +142,7 @@
 	);
 	wp_enqueue_script( 'wp-theme-plugin-editor' );
 	wp_add_inline_script( 'wp-theme-plugin-editor', sprintf( 'jQuery( function( $ ) { wp.themePluginEditor.init( $( "#template" ), %s ); } )', wp_json_encode( $settings ) ) );
+	wp_add_inline_script( 'wp-theme-plugin-editor', sprintf( 'wp.themePluginEditor.themeOrPlugin = "plugin";' ) );
 
 	require_once(ABSPATH . 'wp-admin/admin-header.php');
 
@@ -280,5 +281,21 @@
 <br class="clear" />
 </div>
 <?php
+$hide_notice = get_user_meta( get_current_user_id(), 'hide_plugin_editor_notice', true );
+if ( empty( $hide_notice ) ) :
+?>
+<div id="file-editor-warning" class="notification-dialog-wrap file-editor-warning hide-if-no-js">
+	<div class="notification-dialog-background"></div>
+	<div class="notification-dialog" role="dialog" aria-labelledby="file-editor-warning-title" tabindex="0">
+		<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 site or even leave you staring at the dreaded &#8220;White Screen of Death&#8221;. Your changes may also be overwritten by future updates.' ); ?></p>
+			<p><?php _e( 'If you absolutely must edit a plugin this way, WordPress will attempt to prevent you from being locked out from the dashboard entirely, but cannot guarantee results. Once dismissed, this notice will not appear again.' ); ?></p>
+		</div>
+		<button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss' ); ?></span></button>
+	</div>
+</div>
+<?php
+endif; // editor warning notice
 
 include(ABSPATH . "wp-admin/admin-footer.php");
Index: src/wp-admin/theme-editor.php
===================================================================
--- src/wp-admin/theme-editor.php	(revision 41769)
+++ src/wp-admin/theme-editor.php	(working copy)
@@ -127,6 +127,7 @@
 	);
 	wp_enqueue_script( 'wp-theme-plugin-editor' );
 	wp_add_inline_script( 'wp-theme-plugin-editor', sprintf( 'jQuery( function( $ ) { wp.themePluginEditor.init( $( "#template" ), %s ); } )', wp_json_encode( $settings ) ) );
+	wp_add_inline_script( 'wp-theme-plugin-editor', 'wp.themePluginEditor.themeOrPlugin = "theme";' );
 
 	require_once( ABSPATH . 'wp-admin/admin-header.php' );
 
@@ -309,5 +310,21 @@
 <br class="clear" />
 </div>
 <?php
+$hide_notice = get_user_meta( get_current_user_id(), 'hide_theme_editor_notice', true );
+if ( empty( $hide_notice ) ) :
+?>
+<div id="file-editor-warning" class="notification-dialog-wrap file-editor-warning hide-if-no-js">
+	<div class="notification-dialog-background"></div>
+	<div class="notification-dialog" role="dialog" aria-labelledby="file-editor-warning-title" tabindex="0">
+		<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 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’s no need to change your CSS here &mdash; you can edit and live preview CSS changes in WordPress&#8217;s built in CSS editor.' ); ?></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. Once dismissed, this notice will not appear again.' ); ?></p>
+		</div>
+		<button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss' ); ?></span></button>
+	</div>
+</div>
+<?php
+endif; // editor warning notice
 
 include(ABSPATH . 'wp-admin/admin-footer.php' );
Index: src/wp-includes/script-loader.php
===================================================================
--- src/wp-includes/script-loader.php	(revision 41769)
+++ src/wp-includes/script-loader.php	(working copy)
@@ -478,6 +478,7 @@
 			array( 'singular', 'plural' )
 		),
 	) ) ) );
+	did_action( 'init' ) && $scripts->add_inline_script( 'wp-theme-plugin-editor', sprintf( 'wp.themePluginEditor.nonce = "%s";', wp_create_nonce( 'dismiss-notice' ) ) );
 
 	$scripts->add( 'wp-playlist', "/wp-includes/js/mediaelement/wp-playlist$suffix.js", array( 'wp-util', 'backbone', 'mediaelement' ), false, 1 );
 
