diff --git a/package_manager/src/ComposerUtility.php b/package_manager/src/ComposerUtility.php
index b2713449e457a754a2b23b8ed6cebf95cd431e71..6460b9e13c2aea78085a0468ae5220deb0333b4a 100644
--- a/package_manager/src/ComposerUtility.php
+++ b/package_manager/src/ComposerUtility.php
@@ -57,9 +57,17 @@ class ComposerUtility {
     // pass the home directory in.
     // @see \Composer\Factory::getHomeDir()
     $home = getenv('COMPOSER_HOME');
+    // Disable the automatic generation of .htaccess files in the Composer home
+    // directory, since we are temporarily overriding that directory.
+    // @see \Composer\Factory::createConfig()
+    // @see https://getcomposer.org/doc/06-config.md#htaccess-protect
+    $htaccess = getenv('COMPOSER_HTACCESS_PROTECT');
+
     putenv("COMPOSER_HOME=$dir");
+    putenv("COMPOSER_HTACCESS_PROTECT=false");
     $composer = Factory::create($io, $configuration);
     putenv("COMPOSER_HOME=$home");
+    putenv("COMPOSER_HTACCESS_PROTECT=$htaccess");
 
     return new static($composer);
   }
diff --git a/package_manager/tests/src/Kernel/ComposerUtilityTest.php b/package_manager/tests/src/Kernel/ComposerUtilityTest.php
index 3b3cac5d926bea445be7b3365c4f5735ea63e579..d770cd3a12835108d85b667935c9b59b384cf4d1 100644
--- a/package_manager/tests/src/Kernel/ComposerUtilityTest.php
+++ b/package_manager/tests/src/Kernel/ComposerUtilityTest.php
@@ -4,6 +4,7 @@ namespace Drupal\Tests\package_manager\Kernel;
 
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\package_manager\ComposerUtility;
+use org\bovigo\vfs\vfsStream;
 
 /**
  * @coversDefaultClass \Drupal\package_manager\ComposerUtility
@@ -17,6 +18,17 @@ class ComposerUtilityTest extends KernelTestBase {
    */
   protected static $modules = ['package_manager'];
 
+  /**
+   * Tests that ComposerUtility disables automatic creation of .htaccess files.
+   */
+  public function testHtaccessProtectionDisabled(): void {
+    $dir = vfsStream::setup()->url();
+    file_put_contents($dir . '/composer.json', '{}');
+
+    ComposerUtility::createForDirectory($dir);
+    $this->assertFileNotExists($dir . '/.htaccess');
+  }
+
   /**
    * Data provider for ::testCorePackagesFromLockFile().
    *
diff --git a/tests/fixtures/fake-site/.htaccess b/tests/fixtures/fake-site/.htaccess
deleted file mode 100644
index 14249c50bd7605225950b2d372f352a2dba9252a..0000000000000000000000000000000000000000
--- a/tests/fixtures/fake-site/.htaccess
+++ /dev/null
@@ -1 +0,0 @@
-Deny from all
\ No newline at end of file
diff --git a/tests/fixtures/fake-site/cache/.htaccess b/tests/fixtures/fake-site/cache/.htaccess
deleted file mode 100644
index 14249c50bd7605225950b2d372f352a2dba9252a..0000000000000000000000000000000000000000
--- a/tests/fixtures/fake-site/cache/.htaccess
+++ /dev/null
@@ -1 +0,0 @@
-Deny from all
\ No newline at end of file
diff --git a/tests/src/Build/CoreUpdateTest.php b/tests/src/Build/CoreUpdateTest.php
index 03bfd945b1a1d9132d1950979a16058a655f010d..8b579dd57b15ed670d5755c114fe5f8daa905d95 100644
--- a/tests/src/Build/CoreUpdateTest.php
+++ b/tests/src/Build/CoreUpdateTest.php
@@ -15,6 +15,8 @@ class CoreUpdateTest extends UpdateTestBase {
    * {@inheritdoc}
    */
   protected function createTestSite(string $template): void {
+    $dir = $this->getWorkspaceDirectory();
+
     // Build the test site and alter its copy of core so that it thinks it's
     // running Drupal 9.8.0, which will never actually exist in the real world.
     // Then, prepare a secondary copy of the core code base, masquerading as
@@ -23,7 +25,7 @@ class CoreUpdateTest extends UpdateTestBase {
     // metadata (see fixtures/release-history/drupal.0.0.xml).
     parent::createTestSite($template);
     $this->setCoreVersion($this->getWebRoot() . '/core', '9.8.0');
-    $this->alterPackage($this->getWorkspaceDirectory(), $this->getConfigurationForUpdate('9.8.1'));
+    $this->alterPackage($dir, $this->getConfigurationForUpdate('9.8.1'));
 
     // Install Drupal and ensure it's using the fake release metadata to fetch
     // information about available updates.
@@ -36,6 +38,22 @@ class CoreUpdateTest extends UpdateTestBase {
       'update_test',
     ]);
 
+    // If using the drupal/recommended-project template, we don't expect there
+    // to be an .htaccess file at the project root. One would normally be
+    // generated by Composer when Package Manager or other code creates a
+    // ComposerUtility object in the active directory, except that Package
+    // Manager takes specific steps to prevent that. So, here we're just
+    // confirming that, in fact, Composer's .htaccess protection was disabled.
+    // We don't do this for the drupal/legacy-project template because its
+    // project root, which is also the document root, SHOULD contain a .htaccess
+    // generated by Drupal core.
+    // We do this check because this test uses PHP's built-in web server, which
+    // ignores .htaccess files and everything in them, so a Composer-generated
+    // .htaccess file won't cause this test to fail.
+    if ($template === 'drupal/recommended-project') {
+      $this->assertFileNotExists($dir . '/.htaccess');
+    }
+
     // Ensure that Drupal thinks we are running 9.8.0, then refresh information
     // about available updates.
     $this->assertCoreVersion('9.8.0');