diff --git a/package_manager/src/Validator/WritableFileSystemValidator.php b/package_manager/src/Validator/WritableFileSystemValidator.php
index 4b4ce66add001525f5c0c3d800a9895fd0bf4b07..b8c656d7c65f7937737193e2985e3acba822b1d2 100644
--- a/package_manager/src/Validator/WritableFileSystemValidator.php
+++ b/package_manager/src/Validator/WritableFileSystemValidator.php
@@ -67,6 +67,23 @@ class WritableFileSystemValidator implements PreOperationStageValidatorInterface
       $messages[] = $this->t('The vendor directory "@dir" is not writable.', ['@dir' => $dir]);
     }
 
+    // Ensure the staging root is writable. If it doesn't exist, ensure we will
+    // be able to create it.
+    $dir = $this->pathLocator->getStagingRoot();
+    if (!file_exists($dir)) {
+      $dir = dirname($dir);
+      if (!is_writable($dir)) {
+        $messages[] = $this->t('The staging root directory will not able to be created at "@dir".', [
+          '@dir' => $dir,
+        ]);
+      }
+    }
+    elseif (!is_writable($dir)) {
+      $messages[] = $this->t('The staging root directory "@dir" is not writable.', [
+        '@dir' => $dir,
+      ]);
+    }
+
     if ($messages) {
       $event->addError($messages, $this->t('The file system is not writable.'));
     }
diff --git a/package_manager/tests/src/Kernel/StageTest.php b/package_manager/tests/src/Kernel/StageTest.php
index 65fd2edd505e490dd0ec4020572adb92f8e4ab56..f2eea4f7f2a99c15ae1d28dbba8b1e1237b04d77 100644
--- a/package_manager/tests/src/Kernel/StageTest.php
+++ b/package_manager/tests/src/Kernel/StageTest.php
@@ -44,6 +44,12 @@ class StageTest extends PackageManagerKernelTestBase {
    * @covers ::getStageDirectory
    */
   public function testGetStageDirectory(): void {
+    // In this test, we're working with paths that (probably) don't exist in
+    // the file system at all, so we don't want to validate that the file system
+    // is writable when creating stages.
+    $validator = $this->container->get('package_manager.validator.file_system');
+    $this->container->get('event_dispatcher')->removeSubscriber($validator);
+
     // Don't mirror the active directory from the virtual project into the
     // real file system.
     Beginner::setFixturePath(NULL);
diff --git a/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php b/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php
index 988e339cb82dba1302a59ff61bc057979199d258..d9f25fcb76f179475a3d6ab172095a6f02eb9294 100644
--- a/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php
+++ b/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php
@@ -4,6 +4,7 @@ namespace Drupal\Tests\package_manager\Kernel;
 
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\ValidationResult;
+use Symfony\Component\Filesystem\Filesystem;
 
 /**
  * Unit tests the file system permissions validator.
@@ -86,4 +87,63 @@ class WritableFileSystemValidatorTest extends PackageManagerKernelTestBase {
     $this->assertResults($expected_results, PreCreateEvent::class);
   }
 
+  /**
+   * Data provider for ::testStagingRootPermissions().
+   *
+   * @return mixed[][]
+   *   The test cases.
+   */
+  public function providerStagingRootPermissions(): array {
+    $writable_permission = 0777;
+    $non_writable_permission = 0444;
+    $summary = t('The file system is not writable.');
+    return [
+      'writable staging root exists' => [
+        $writable_permission,
+        [],
+        FALSE,
+      ],
+      'write-protected staging root exists' => [
+        $non_writable_permission,
+        [
+          ValidationResult::createError(['The staging root directory "vfs://root/stage" is not writable.'], $summary),
+        ],
+        FALSE,
+      ],
+      'staging root does not exist, parent directory not writable' => [
+        $non_writable_permission,
+        [
+          ValidationResult::createError(['The staging root directory will not able to be created at "vfs://root".'], $summary),
+        ],
+        TRUE,
+      ],
+    ];
+  }
+
+  /**
+   * Tests that the staging root's permissions are validated.
+   *
+   * @param int $permissions
+   *   The file permissions to apply to the staging root, or its parent
+   *   directory, depending on the value of $delete_staging_root.
+   * @param array $expected_results
+   *   The expected validation results.
+   * @param bool $delete_staging_root
+   *   Whether the staging root directory will exist at all.
+   *
+   * @dataProvider providerStagingRootPermissions
+   */
+  public function testStagingRootPermissions(int $permissions, array $expected_results, bool $delete_staging_root): void {
+    $dir = $this->container->get('package_manager.path_locator')
+      ->getStagingRoot();
+
+    if ($delete_staging_root) {
+      $fs = new Filesystem();
+      $fs->remove($dir);
+      $dir = dirname($dir);
+    }
+    $this->assertTrue(chmod($dir, $permissions));
+    $this->assertResults($expected_results, PreCreateEvent::class);
+  }
+
 }