diff --git src/wp-admin/includes/plugin.php src/wp-admin/includes/plugin.php
index 233d990..f26637c 100644
--- src/wp-admin/includes/plugin.php
+++ src/wp-admin/includes/plugin.php
@@ -46,6 +46,7 @@
  * - 'TextDomain' - Plugin's text domain for localization.
  * - 'DomainPath' - Plugin's relative directory path to .mo files.
  * - 'Network' - Boolean. Whether the plugin can only be activated network wide.
+ * - 'Private' - Boolean. Whether the plugin should be excluded from update checks.
  *
  * Some users have issues with opening large files and manipulating the contents
  * for want is usually the first 1kiB or 2kiB. This function stops pulling in
@@ -81,6 +82,7 @@ function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {
 		'TextDomain' => 'Text Domain',
 		'DomainPath' => 'Domain Path',
 		'Network' => 'Network',
+		'Private' => 'Private',
 		// Site Wide Only is deprecated in favor of Network.
 		'_sitewide' => 'Site Wide Only',
 	);
@@ -95,6 +97,8 @@ function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {
 	$plugin_data['Network'] = ( 'true' == strtolower( $plugin_data['Network'] ) );
 	unset( $plugin_data['_sitewide'] );
 
+	$plugin_data['Private'] = ( 'true' == strtolower( $plugin_data['Private'] ) );
+
 	if ( $markup || $translate ) {
 		$plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate );
 	} else {
diff --git src/wp-includes/class-wp-theme.php src/wp-includes/class-wp-theme.php
index ad70a4b..223040a 100644
--- src/wp-includes/class-wp-theme.php
+++ src/wp-includes/class-wp-theme.php
@@ -27,6 +27,7 @@ final class WP_Theme implements ArrayAccess {
 		'Tags'        => 'Tags',
 		'TextDomain'  => 'Text Domain',
 		'DomainPath'  => 'Domain Path',
+		'Private'     => 'Private',
 	);
 
 	/**
@@ -565,7 +566,7 @@ final class WP_Theme implements ArrayAccess {
 	 * @since 3.4.0
 	 * @access public
 	 *
-	 * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags.
+	 * @param string $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags, Private.
 	 * @return string|false String on success, false on failure.
 	 */
 	public function get( $header ) {
@@ -670,6 +671,9 @@ final class WP_Theme implements ArrayAccess {
 			case 'AuthorURI' :
 				$value = esc_url_raw( $value );
 				break;
+			case 'Private' :
+				$value = 'true' === strtolower( $value );
+				break;
 			case 'Tags' :
 				$value = array_filter( array_map( 'trim', explode( ',', strip_tags( $value ) ) ) );
 				break;
diff --git src/wp-includes/update.php src/wp-includes/update.php
index c39322e..19ceef5 100644
--- src/wp-includes/update.php
+++ src/wp-includes/update.php
@@ -200,6 +200,14 @@ function wp_update_plugins( $extra_stats = array() ) {
 		require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
 
 	$plugins = get_plugins();
+
+	// Omit private plugins
+	foreach ( $plugins as $file => $p ) {
+		if ( $p['Private'] ) {
+			unset( $plugins[$file] );
+		}
+	}
+
 	$translations = wp_get_installed_translations( 'plugins' );
 
 	$active  = get_option( 'active_plugins', array() );
@@ -366,6 +374,11 @@ function wp_update_themes( $extra_stats = array() ) {
 	foreach ( $installed_themes as $theme ) {
 		$checked[ $theme->get_stylesheet() ] = $theme->get('Version');
 
+		// Omit private themes
+		if ( $theme->get('Private') ) {
+			continue;
+		}
+
 		$themes[ $theme->get_stylesheet() ] = array(
 			'Name'       => $theme->get('Name'),
 			'Title'      => $theme->get('Name'),
