diff --git a/core/lib/Drupal/Core/Recipe/Recipe.php b/core/lib/Drupal/Core/Recipe/Recipe.php
index 89e7b0ed742de6e452dee26a1a1e527be99d562d..c9f5f055932c9ec98bb5a403d4c580105862a56c 100644
--- a/core/lib/Drupal/Core/Recipe/Recipe.php
+++ b/core/lib/Drupal/Core/Recipe/Recipe.php
@@ -383,14 +383,23 @@ private static function validateConfigActions(mixed $value, ExecutionContextInte
 
     $configurator = new RecipeConfigurator($recipe_being_validated['recipes'] ?? [], $include_path);
 
+    /** @var \Drupal\Core\Extension\ModuleExtensionList $module_list */
+    $module_list = \Drupal::service('extension.list.module');
     // The config provider must either be an already-installed module or theme,
     // or an extension being installed by this recipe or a recipe it depends on.
     $all_extensions = [
-      ...array_keys(\Drupal::service('extension.list.module')->getAllInstalledInfo()),
+      ...array_keys($module_list->getAllInstalledInfo()),
       ...array_keys(\Drupal::service('extension.list.theme')->getAllInstalledInfo()),
       ...$recipe_being_validated['install'] ?? [],
       ...$configurator->listAllExtensions(),
     ];
+    // Explicitly treat required modules as installed, even if Drupal isn't
+    // installed yet, because we know they WILL be installed.
+    foreach ($module_list->getAllAvailableInfo() as $name => $info) {
+      if (!empty($info['required'])) {
+        $all_extensions[] = $name;
+      }
+    }
 
     if (!in_array($config_provider, $all_extensions, TRUE)) {
       $context->addViolation('Config actions cannot be applied to %config_name because the %config_provider extension is not installed, and is not installed by this recipe or any of the recipes it depends on.', [
diff --git a/core/tests/Drupal/KernelTests/Core/Recipe/RecipeTest.php b/core/tests/Drupal/KernelTests/Core/Recipe/RecipeTest.php
index 9db4abe5709ce80c4d80463ce66052d0fc1ea2fd..b63861276ff34092cfb8ddc522fa3a2a03d99144 100644
--- a/core/tests/Drupal/KernelTests/Core/Recipe/RecipeTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Recipe/RecipeTest.php
@@ -8,6 +8,7 @@
 use Drupal\Core\Recipe\RecipeFileException;
 use Drupal\Core\Recipe\RecipePreExistingConfigException;
 use Drupal\Core\Recipe\RecipeRunner;
+use Drupal\FunctionalTests\Core\Recipe\RecipeTestTrait;
 use Drupal\KernelTests\KernelTestBase;
 
 /**
@@ -16,6 +17,8 @@
  */
 class RecipeTest extends KernelTestBase {
 
+  use RecipeTestTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -80,4 +83,19 @@ public function testExampleRecipe(): void {
     $this->assertSame($this->config('text.settings')->get('default_summary_length'), 700);
   }
 
+  public function testImplicitlyRequiredModule(): void {
+    $this->disableModules(['user']);
+    $recipe = $this->createRecipe([
+      'name' => 'Actions on config from required module',
+      'config' => [
+        'actions' => [
+          'user.role.authenticated' => [
+            'grantPermission' => 'access administration pages',
+          ],
+        ],
+      ],
+    ]);
+    $this->assertIsObject($recipe);
+  }
+
 }