Index: src/wp-includes/meta.php
===================================================================
--- src/wp-includes/meta.php	(revision 43140)
+++ src/wp-includes/meta.php	(working copy)
@@ -952,6 +952,18 @@
 function is_protected_meta( $meta_key, $meta_type = null ) {
 	$protected = ( '_' == $meta_key[0] );
 
+	if( $meta_type ) {
+		/**
+		 * Filters whether a meta key is considered protected.
+		 *
+		 * @since 5.0.0
+		 *
+		 * @param bool $protected Whether the key is considered protected.
+		 * @param string $meta_key Meta key.
+		 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user).
+		 */
+		$protected = apply_filters( "protected_{$meta_type}_meta_{$meta_key}", $protected, $meta_key, $meta_type );
+	}
 	/**
 	 * Filters whether a meta key is considered protected.
 	 *
@@ -1026,14 +1038,15 @@
 		$wp_meta_keys = array();
 	}
 
-	$defaults = array(
-		'type'              => 'string',
-		'description'       => '',
-		'single'            => false,
-		'sanitize_callback' => null,
-		'auth_callback'     => null,
-		'show_in_rest'      => false,
-	);
+	$defaults = [
+		'type'               => 'string',
+		'description'        => '',
+		'single'             => false,
+		'protected_callback' => null,
+		'sanitize_callback'  => null,
+		'auth_callback'      => null,
+		'show_in_rest'       => false,
+	];
 
 	// There used to be individual args for sanitize and auth callbacks
 	$has_old_sanitize_cb = false;
@@ -1067,6 +1080,10 @@
 	$args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
 	$args = wp_parse_args( $args, $defaults );
 
+	if ( is_callable( $args['protected_callback'] ) ) {
+		add_filter( "protected_{$meta_type}_meta_{$meta_key}", $args['protected_callback'], 10, 1 );
+	}
+
 	// If `auth_callback` is not provided, fall back to `is_protected_meta()`.
 	if ( empty( $args['auth_callback'] ) ) {
 		if ( is_protected_meta( $meta_key, $object_type ) ) {
@@ -1149,6 +1166,10 @@
 		remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] );
 	}
 
+	if ( isset( $args['protected_callback'] ) && is_callable( $args['protected_callback'] ) ) {
+		remove_filter( "protected_{$object_type}_meta_{$meta_key}", $args['protected_callback'] );
+	}
+
 	unset( $wp_meta_keys[ $object_type ][ $meta_key ] );
 
 	// Do some clean up
