diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index b25a0d935e79ef29b80a4a75500462e9a4570f8a..49744524a2ac99bdd659e71adcb1a0443e1cde05 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -20,6 +20,7 @@
 use Drupal\Core\DependencyInjection\YamlFileLoader;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\File\MimeType\MimeTypeGuesser;
+use Drupal\Core\Http\TrustedHostsRequestFactory;
 use Drupal\Core\Language\Language;
 use Drupal\Core\PageCache\RequestPolicyInterface;
 use Drupal\Core\PhpStorage\PhpStorageFactory;
@@ -1297,13 +1298,24 @@ public static function validateHostname(Request $request) {
    *   TRUE if the Host header is trusted, FALSE otherwise.
    *
    * @see https://www.drupal.org/node/1992030
+   * @see \Drupal\Core\Http\TrustedHostsRequestFactory
    */
   protected static function setupTrustedHosts(Request $request, $host_patterns) {
     $request->setTrustedHosts($host_patterns);
 
     // Get the host, which will validate the current request.
     try {
-      $request->getHost();
+      $host = $request->getHost();
+
+      // Fake requests created through Request::create() without passing in the
+      // server variables from the main request have a default host of
+      // 'localhost'. If 'localhost' does not match any of the trusted host
+      // patterns these fake requests would fail the host verification. Instead,
+      // TrustedHostsRequestFactory makes sure to pass in the server variables
+      // from the main request.
+      $request_factory = new TrustedHostsRequestFactory($host);
+      Request::setFactory([$request_factory, 'createRequest']);
+
     }
     catch (\UnexpectedValueException $e) {
       return FALSE;
diff --git a/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php b/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..bc518d7a07df5984c7e13dc8a123ea6d0a384bca
--- /dev/null
+++ b/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Http\TrustedHostsRequestFactory.
+ */
+
+namespace Drupal\Core\Http;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Provides a request factory for requests using host verification.
+ *
+ * Because the trusted host patterns for requests are stored statically, they
+ * are consulted even for fake request created with Request::create(), whose
+ * host is 'localhost' by default. Such requests would fail host verification
+ * unless 'localhost' matches one of the trusted host patterns. To circumvent
+ * this problem, this factory injects the server variables from the main request
+ * into each newly created request, so that the host is correctly set even for
+ * fake requests and they properly pass host verification.
+ *
+ * @see \Drupal\Core\DrupalKernel::setupTrustedHosts()
+ */
+class TrustedHostsRequestFactory {
+
+  /**
+   * The host of the main request.
+   *
+   * @var string
+   */
+  protected $host;
+
+  /**
+   * Creates a new TrustedHostsRequestFactory.
+   *
+   * @param string $host
+   *   The host of the main request.
+   */
+  public function __construct($host) {
+    $this->host = (string) $host;
+  }
+
+  /**
+   * Creates a new request object.
+   *
+   * @param array $query
+   *   (optional) The query (GET) or request (POST) parameters.
+   * @param array $request
+   *   (optional) An array of request variables.
+   * @param array $attributes
+   *   (optioanl) An array of attributes.
+   * @param array $cookies
+   *   (optional) The request cookies ($_COOKIE).
+   * @param array $files
+   *   (optional) The request files ($_FILES).
+   * @param array $server
+   *   (optional) The server parameters ($_SERVER).
+   * @param string $content
+   *   (optional) The raw body data.
+   *
+   * @return \Symfony\Component\HttpFoundation\Request
+   *   A new request object.
+   **/
+  public function createRequest(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) {
+    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);
+  }
+
+}
diff --git a/core/modules/system/src/Tests/System/TrustedHostsTest.php b/core/modules/system/src/Tests/System/TrustedHostsTest.php
index 2be2c8b70fe58b5844357e732662920e38694bf6..3719bd1ebf684eb06b04ff29adb73cb6764bdb52 100644
--- a/core/modules/system/src/Tests/System/TrustedHostsTest.php
+++ b/core/modules/system/src/Tests/System/TrustedHostsTest.php
@@ -8,7 +8,10 @@
 namespace Drupal\system\Tests\System;
 
 use Drupal\Core\Site\Settings;
+use Drupal\Core\Url;
 use Drupal\simpletest\WebTestBase;
+use Drupal\user\Entity\User;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Tests output on the status overview page.
@@ -59,4 +62,55 @@ public function testStatusPageWithConfiguration() {
     $this->assertRaw(t('The trusted_host_patterns setting is set to allow'));
   }
 
+  /**
+   * Tests that fake requests have the proper host configured.
+   *
+   * @see \Drupal\Core\Http\TrustedHostsRequestFactory
+   */
+  public function testFakeRequests() {
+    $this->container->get('module_installer')->install(['trusted_hosts_test']);
+
+    $host = $this->container->get('request_stack')->getCurrentRequest()->getHost();
+    $settings['settings']['trusted_host_patterns'] = (object) array(
+      'value' => array('^' . preg_quote($host) . '$'),
+      'required' => TRUE,
+    );
+
+    $this->writeSettings($settings);
+
+    $this->drupalGet('trusted-hosts-test/fake-request');
+    $this->assertText('Host: ' . $host);
+  }
+
+  /**
+   * Tests that shortcut module works together with host verification.
+   */
+  public function testShortcut() {
+    $this->container->get('module_installer')->install(['block', 'shortcut']);
+    $this->rebuildContainer();
+
+    /** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */
+    $entity_manager = $this->container->get('entity.manager');
+    $shortcut_storage = $entity_manager->getStorage('shortcut');
+
+    $shortcut = $shortcut_storage->create([
+      'title' => $this->randomString(),
+      'link' => 'internal:/admin/reports/status',
+      'shortcut_set' => 'default',
+    ]);
+    $shortcut_storage->save($shortcut);
+
+    // Grant the current user access to see the shortcuts.
+    $role_storage = $entity_manager->getStorage('user_role');
+    $roles = $this->loggedInUser->getRoles(TRUE);
+    /** @var \Drupal\user\RoleInterface $role */
+    $role = $role_storage->load(reset($roles));
+    $role->grantPermission('access shortcuts')->save();
+
+    $this->drupalPlaceBlock('shortcuts');
+
+    $this->drupalGet('');
+    $this->assertLink($shortcut->label());
+  }
+
 }
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
new file mode 100644
index 0000000000000000000000000000000000000000..b97c45c543e0c07c3d5cb37954a9b7f46148b9c4
--- /dev/null
+++ b/core/modules/system/tests/modules/trusted_hosts_test/src/Controller/TrustedHostsTestController.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\trusted_hosts_test\Controller\TrustedHostsTestController.
+ */
+
+namespace Drupal\trusted_hosts_test\Controller;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Provides a test controller for testing the trusted hosts setting.
+ */
+class TrustedHostsTestController {
+
+  /**
+   * Creates a fake request and prints out its host.
+   */
+  public function fakeRequestHost() {
+    $request = Request::create('/');
+    return ['#markup' => 'Host: ' . $request->getHost()];
+  }
+
+}
+
diff --git a/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.info.yml b/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..20f41bcb84a01235e0a22058e9da0c4bc4f8d8c3
--- /dev/null
+++ b/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.info.yml
@@ -0,0 +1,5 @@
+type: module
+name: 'Trusted hosts test module'
+core: 8.x
+package: Testing
+version: VERSION
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
new file mode 100644
index 0000000000000000000000000000000000000000..834aeace01e8844e3a972945151dff4242d33097
--- /dev/null
+++ b/core/modules/system/tests/modules/trusted_hosts_test/trusted_hosts_test.routing.yml
@@ -0,0 +1,6 @@
+trusted_hosts_test.fake_request:
+  path: '/trusted-hosts-test/fake-request'
+  defaults:
+    _controller: 'Drupal\trusted_hosts_test\Controller\TrustedHostsTestController::fakeRequestHost'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/tests/Drupal/Tests/Core/Http/TrustedHostsRequestFactoryTest.php b/core/tests/Drupal/Tests/Core/Http/TrustedHostsRequestFactoryTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..643b821b1f2fa1b3ab27804e6492f2ff3f776527
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Http/TrustedHostsRequestFactoryTest.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Tests\Core\Http\TrustedHostsRequestFactoryTest.
+ */
+
+namespace Drupal\Tests\Core\Http;
+use Drupal\Core\Http\TrustedHostsRequestFactory;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the trusted hosts request factory.
+ *
+ * @coversDefaultClass \Drupal\Core\Http\TrustedHostsRequestFactory
+ * @group Http
+ */
+class TrustedHostsRequestFactoryTest extends UnitTestCase {
+
+  /**
+   * Tests TrustedHostsRequestFactory::createRequest().
+   *
+   * @param string $host
+   *   The host to pass into TrustedHostsRequestFactory.
+   * @param array $server
+   *   The server array to pass into
+   *   TrustedHostsRequestFactory::createRequest().
+   * @param string $expected
+   *   The expected host of the created request.
+   *
+   * @covers ::createRequest
+   * @dataProvider providerTestCreateRequest
+   */
+  public function testCreateRequest($host, $server, $expected) {
+    $request_factory = new TrustedHostsRequestFactory($host);
+    $request = $request_factory->createRequest([], [], [], [], [], $server, []);
+    $this->assertEquals($expected, $request->getHost());
+  }
+
+  /**
+   * Provides data for testCreateRequest().
+   *
+   * @return array
+   *   An array of test cases, where each test case is an array with the
+   *   following values:
+   *   - A string containing the host to pass into TrustedHostsRequestFactory.
+   *   - An array containing the server array to pass into
+   *   TrustedHostsRequestFactory::createRequest().
+   *   - A string containing the expected host of the created request.
+   */
+  public function providerTestCreateRequest() {
+    $tests = [];
+    $tests[] = ['example.com', [], 'example.com'];
+    $tests[] = ['localhost', [], 'localhost'];
+    $tests[] = ['localhost', ['HTTP_HOST' => 'localhost'], 'localhost'];
+    $tests[] = ['example.com', ['HTTP_HOST' => 'localhost'], 'example.com'];
+    return $tests;
+  }
+
+}