diff --git a/core/modules/content_moderation/content_moderation.module b/core/modules/content_moderation/content_moderation.module
index df1c2225bb5a21f8009217c1852e4556fd5e30a8..4b07e45790b44deab1f302bc8a3eeeb27e6990bd 100644
--- a/core/modules/content_moderation/content_moderation.module
+++ b/core/modules/content_moderation/content_moderation.module
@@ -319,13 +319,3 @@ function content_moderation_workflow_update(WorkflowInterface $entity) {
   // Clear field cache so extra field is added or removed.
   \Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
 }
-
-/**
- * Implements hook_rest_resource_alter().
- */
-function content_moderation_rest_resource_alter(&$definitions) {
-  // ContentModerationState is an internal entity type. Therefore it should not
-  // be exposed via REST.
-  // @see \Drupal\content_moderation\ContentModerationStateAccessControlHandler
-  unset($definitions['entity:content_moderation_state']);
-}
diff --git a/core/modules/content_moderation/src/Entity/ContentModerationState.php b/core/modules/content_moderation/src/Entity/ContentModerationState.php
index b56f0d8115b0b4e0727d8798f83940e0c741f7cf..abb92eb8411ebedef8196d35f17e676dc1133cc3 100644
--- a/core/modules/content_moderation/src/Entity/ContentModerationState.php
+++ b/core/modules/content_moderation/src/Entity/ContentModerationState.php
@@ -31,6 +31,7 @@
  *   data_table = "content_moderation_state_field_data",
  *   revision_data_table = "content_moderation_state_field_revision",
  *   translatable = TRUE,
+ *   internal = TRUE,
  *   entity_keys = {
  *     "id" = "id",
  *     "revision" = "revision_id",
diff --git a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateResourceTest.php b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateResourceTest.php
index cc09e5921a71ec728804c2f57f81a96890765d6a..2ea1d8f901ff39c908b52e5d5b56cd09d87adf64 100644
--- a/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateResourceTest.php
+++ b/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateResourceTest.php
@@ -18,7 +18,7 @@ class ContentModerationStateResourceTest extends KernelTestBase {
   public static $modules = ['serialization', 'rest', 'content_moderation'];
 
   /**
-   * @see content_moderation_rest_resource_alter()
+   * @see \Drupal\content_moderation\Entity\ContentModerationState
    */
   public function testCreateContentModerationStateResource() {
     $this->setExpectedException(PluginNotFoundException::class, 'The "entity:content_moderation_state" plugin does not exist.');
diff --git a/core/modules/rest/src/Plugin/Deriver/EntityDeriver.php b/core/modules/rest/src/Plugin/Deriver/EntityDeriver.php
index a74e8b2a61f650a2d83acdab52f213b7fc8b28a0..e631f5da3ee4e50265dc74180a9799b753720202 100644
--- a/core/modules/rest/src/Plugin/Deriver/EntityDeriver.php
+++ b/core/modules/rest/src/Plugin/Deriver/EntityDeriver.php
@@ -65,6 +65,10 @@ public function getDerivativeDefinitions($base_plugin_definition) {
     if (!isset($this->derivatives)) {
       // Add in the default plugin configuration and the resource type.
       foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
+        if ($entity_type->isInternal()) {
+          continue;
+        }
+
         $this->derivatives[$entity_type_id] = [
           'id' => 'entity:' . $entity_type_id,
           'entity_type' => $entity_type_id,
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceRestTestCoverageTest.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceRestTestCoverageTest.php
index d10d55c245be84e42df28e95fcf9d81ca0ab9a3e..6421472067e05f52e73f2d9b6b8a02fef175c629 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceRestTestCoverageTest.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceRestTestCoverageTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\rest\Functional\EntityResource;
 
+use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Tests\BrowserTestBase;
 
 /**
@@ -45,15 +46,11 @@ protected function setUp() {
 
     $this->definitions = $this->container->get('entity_type.manager')->getDefinitions();
 
-    // Remove definitions for which the REST resource plugin definition was
-    // removed via hook_rest_resource_alter(). Entity types which are never
-    // exposed via REST also don't need test coverage.
-    $resource_plugin_ids = array_keys($this->container->get('plugin.manager.rest')->getDefinitions());
-    foreach (array_keys($this->definitions) as $entity_type_id) {
-      if (!in_array("entity:$entity_type_id", $resource_plugin_ids, TRUE)) {
-        unset($this->definitions[$entity_type_id]);
-      }
-    }
+    // Entity types marked as "internal" are not exposed by the entity REST
+    // resource plugin and hence also don't need test coverage.
+    $this->definitions = array_filter($this->definitions, function (EntityTypeInterface $entity_type) {
+      return !$entity_type->isInternal();
+    });
   }
 
   /**