diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 766931fbd1c6be3db73f13cb01837c4824e1a980..74dfb3f4d5afec2a6b4c9aabfb99779056c62bd6 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -6,11 +6,14 @@
  */
 
 use Drupal\Component\Utility\Crypt;
+use Drupal\Core\Http\InputBag;
 use Drupal\Core\Logger\RfcLogLevel;
 use Drupal\Core\Test\TestDatabase;
 use Drupal\Core\Utility\Error;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\InputBag as SymfonyInputBag;
 
 /**
  * Minimum allowed version of PHP for Drupal to be bootstrapped.
@@ -130,6 +133,23 @@
 //   alias once Drupal is running Symfony 5.3 or higher.
 class_alias('Drupal\Core\Http\KernelEvent', 'Symfony\Component\HttpKernel\Event\KernelEvent', TRUE);
 
+/**
+ * Set up the Symfony Request factory for forward compatibility with Symfony 5.
+ *
+ * @todo Remove this when Symfony 4 is no longer supported.
+ */
+Request::setFactory(
+  function ($query, $request, $attributes, $cookies, $files, $server, $content) {
+    $request = new Request($query, $request, $attributes, $cookies, $files, $server, $content);
+    foreach (['request', 'query', 'cookies'] as $bag) {
+      if (!($bag instanceof SymfonyInputBag)) {
+        $request->$bag = new InputBag($request->$bag->all());
+      }
+    }
+    return $request;
+  }
+);
+
 /**
  * Returns and optionally sets the filename for a system resource.
  *
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index afb27395431d907435ec797ef42b3215ae43da1a..94ab081d8c4864672da0211249d05063c5661ba2 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -17,7 +17,6 @@
 use Drupal\Core\DependencyInjection\YamlFileLoader;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\File\MimeType\MimeTypeGuesser;
-use Drupal\Core\Http\InputBag;
 use Drupal\Core\Http\TrustedHostsRequestFactory;
 use Drupal\Core\Installer\InstallerKernel;
 use Drupal\Core\Installer\InstallerRedirectTrait;
@@ -34,7 +33,6 @@
 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
 use Symfony\Component\HttpKernel\TerminableInterface;
-use Symfony\Component\HttpFoundation\InputBag as SymfonyInputBag;
 use TYPO3\PharStreamWrapper\Manager as PharStreamWrapperManager;
 use TYPO3\PharStreamWrapper\Behavior as PharStreamWrapperBehavior;
 use TYPO3\PharStreamWrapper\PharStreamWrapper;
@@ -695,14 +693,6 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch =
     // Ensure sane PHP environment variables.
     static::bootEnvironment();
 
-    // Replace ParameterBag with InputBag for compatibility with Symfony 5.
-    // @todo Remove this when Symfony 4 is no longer supported.
-    foreach (['request', 'query', 'cookies'] as $bag) {
-      if (!($bag instanceof SymfonyInputBag)) {
-        $request->$bag = new InputBag($request->$bag->all());
-      }
-    }
-
     try {
       $this->initializeSettings($request);
 
diff --git a/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php b/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php
index f1ddd55a747036d89d1828ee96414e0a84d36e95..7c46418138e437fefb05902385eaeaeeac058c37 100644
--- a/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php
+++ b/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Core\Http;
 
+use Symfony\Component\HttpFoundation\InputBag as SymfonyInputBag;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
@@ -61,7 +62,17 @@ public function createRequest(array $query = [], array $request = [], array $att
     if (empty($server['HTTP_HOST']) || ($server['HTTP_HOST'] === 'localhost' && $this->host !== 'localhost')) {
       $server['HTTP_HOST'] = $this->host;
     }
-    return new Request($query, $request, $attributes, $cookies, $files, $server, $content);
+    $request = new Request($query, $request, $attributes, $cookies, $files, $server, $content);
+
+    // Replace ParameterBag with InputBag for compatibility with Symfony 5.
+    // @todo Remove this when Symfony 4 is no longer supported.
+    foreach (['request', 'query', 'cookies'] as $bag) {
+      if (!($bag instanceof SymfonyInputBag)) {
+        $request->$bag = new InputBag($request->$bag->all());
+      }
+    }
+
+    return $request;
   }
 
 }
diff --git a/core/modules/system/tests/modules/trusted_hosts_test/src/Controller/TrustedHostsTestController.php b/core/modules/system/tests/modules/trusted_hosts_test/src/Controller/TrustedHostsTestController.php
index bb768421f0e167f4c1517cefbb933c5f0a0b72c8..78d20d6a4a497df30df055d801b7a60dd5c9d15c 100644
--- a/core/modules/system/tests/modules/trusted_hosts_test/src/Controller/TrustedHostsTestController.php
+++ b/core/modules/system/tests/modules/trusted_hosts_test/src/Controller/TrustedHostsTestController.php
@@ -17,4 +17,12 @@ public function fakeRequestHost() {
     return ['#markup' => 'Host: ' . $request->getHost()];
   }
 
+  /**
+   * Creates a fake request and prints out the class name of the specified bag.
+   */
+  public function bagType($bag) {
+    $request = Request::create('/');
+    return ['#markup' => 'Type: ' . get_class($request->$bag)];
+  }
+
 }
diff --git a/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.routing.yml b/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.routing.yml
index 607710873c90da189b0acaab0de59fd4741117b6..0fe1e2b33136eeb978e27aacf311863af2cb4dfa 100644
--- a/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.routing.yml
+++ b/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.routing.yml
@@ -4,3 +4,10 @@ trusted_hosts_test.fake_request:
     _controller: '\Drupal\trusted_hosts_test\Controller\TrustedHostsTestController::fakeRequestHost'
   requirements:
     _access: 'TRUE'
+
+trusted_hosts_test.bag_type:
+  path: '/trusted-hosts-test/bag-type/{bag}'
+  defaults:
+    _controller: '\Drupal\trusted_hosts_test\Controller\TrustedHostsTestController::bagType'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/system/tests/src/Functional/System/TrustedHostsTest.php b/core/modules/system/tests/src/Functional/System/TrustedHostsTest.php
index db0cb122cf7212bde3c840582ef79c0aca616ba1..9cc455ad66a561d7a027fd277f27bd0c922cb6f3 100644
--- a/core/modules/system/tests/src/Functional/System/TrustedHostsTest.php
+++ b/core/modules/system/tests/src/Functional/System/TrustedHostsTest.php
@@ -111,4 +111,28 @@ public function testShortcut() {
     $this->assertSession()->linkExists($shortcut->label());
   }
 
+  /**
+   * Tests that the request bags have the correct classes.
+   *
+   * @todo Remove this when Symfony 4 is no longer supported.
+   *
+   * @see \Drupal\Core\Http\TrustedHostsRequestFactory
+   */
+  public function testRequestBags() {
+    $this->container->get('module_installer')->install(['trusted_hosts_test']);
+
+    $host = $this->container->get('request_stack')->getCurrentRequest()->getHost();
+    $settings['settings']['trusted_host_patterns'] = (object) [
+      'value' => ['^' . preg_quote($host) . '$'],
+      'required' => TRUE,
+    ];
+
+    $this->writeSettings($settings);
+
+    foreach (['request', 'query', 'cookies'] as $bag) {
+      $this->drupalGet('trusted-hosts-test/bag-type/' . $bag);
+      $this->assertSession()->pageTextContains('InputBag');
+    }
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Http/InputBagTest.php b/core/tests/Drupal/Tests/Core/Http/InputBagTest.php
index 43b24db1298cf139b5283394ad2901a6f67fd453..f2120e4afe5f441a43de31afe2148fac0e8123cc 100644
--- a/core/tests/Drupal/Tests/Core/Http/InputBagTest.php
+++ b/core/tests/Drupal/Tests/Core/Http/InputBagTest.php
@@ -4,6 +4,7 @@
 
 use Drupal\Core\Http\InputBag;
 use Drupal\Tests\UnitTestCase;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * @coversDefaultClass \Drupal\Core\Http\InputBag
@@ -28,4 +29,13 @@ public function testAll() {
     $input_bag->all('bad');
   }
 
+  /**
+   * @coversNothing
+   * @todo Remove this when Symfony 4 is no longer supported.
+   */
+  public function testRequestFactory() {
+    $request = Request::create('');
+    $this->assertInstanceOf(InputBag::class, $request->query);
+  }
+
 }