diff --git a/core/lib/Drupal/Core/Extension/ExtensionLifecycle.php b/core/lib/Drupal/Core/Extension/ExtensionLifecycle.php
index f3b4f0c7f34785cc94f0b1efd7c1f692c52eb7b4..9a782ace87268e8a29309a23e696e54d5e49cd76 100644
--- a/core/lib/Drupal/Core/Extension/ExtensionLifecycle.php
+++ b/core/lib/Drupal/Core/Extension/ExtensionLifecycle.php
@@ -19,6 +19,11 @@ final class ExtensionLifecycle {
    */
   const LIFECYCLE_IDENTIFIER = 'lifecycle';
 
+  /**
+   * The string used to identify the lifecycle link in an .info.yml file.
+   */
+  const LIFECYCLE_LINK_IDENTIFIER = 'lifecycle_link';
+
   /**
    * Extension is experimental. Warnings will be shown if installed.
    */
diff --git a/core/lib/Drupal/Core/Extension/InfoParserDynamic.php b/core/lib/Drupal/Core/Extension/InfoParserDynamic.php
index 9779f39c8e006f7938485b5b1874a96fb8d255f3..718be0aa53b11e45e4271e11f06b6bbde5834a71 100644
--- a/core/lib/Drupal/Core/Extension/InfoParserDynamic.php
+++ b/core/lib/Drupal/Core/Extension/InfoParserDynamic.php
@@ -108,14 +108,23 @@ public function parse($filename) {
         $parsed_info['version'] = \Drupal::VERSION;
       }
       $parsed_info += [ExtensionLifecycle::LIFECYCLE_IDENTIFIER => ExtensionLifecycle::STABLE];
-      if (!ExtensionLifecycle::isValid($parsed_info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER])) {
+      $lifecycle = $parsed_info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER];
+      if (!ExtensionLifecycle::isValid($lifecycle)) {
         $valid_values = [
           ExtensionLifecycle::EXPERIMENTAL,
           ExtensionLifecycle::STABLE,
           ExtensionLifecycle::DEPRECATED,
           ExtensionLifecycle::OBSOLETE,
         ];
-        throw new InfoParserException("'lifecycle: {$parsed_info[ExtensionLifecycle::LIFECYCLE_IDENTIFIER]}' is not valid in $filename. Valid values are: '" . implode("', '", $valid_values) . "'.");
+        throw new InfoParserException("'lifecycle: {$lifecycle}' is not valid in $filename. Valid values are: '" . implode("', '", $valid_values) . "'.");
+      }
+      if (in_array($lifecycle, [ExtensionLifecycle::DEPRECATED, ExtensionLifecycle::OBSOLETE], TRUE)) {
+        if (empty($parsed_info[ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER])) {
+          throw new InfoParserException(sprintf("Extension %s (%s) has 'lifecycle: %s' but is missing a '%s' entry.", $parsed_info['name'], $filename, $lifecycle, ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER));
+        }
+        if (!filter_var($parsed_info[ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER], FILTER_VALIDATE_URL)) {
+          throw new InfoParserException(sprintf("Extension %s (%s) has a '%s' entry that is not a valid URL.", $parsed_info['name'], $filename, ExtensionLifecycle::LIFECYCLE_LINK_IDENTIFIER));
+        }
       }
     }
     return $parsed_info;
diff --git a/core/modules/entity_reference/entity_reference.info.yml b/core/modules/entity_reference/entity_reference.info.yml
index c9683bb14ba490b2f31791775f5bc0611f586202..27616b0a5c784b5d98e488780dc70a85ddd6fd69 100644
--- a/core/modules/entity_reference/entity_reference.info.yml
+++ b/core/modules/entity_reference/entity_reference.info.yml
@@ -2,6 +2,7 @@ name: 'Entity Reference'
 type: module
 description: 'Obsolete. All the functionality has been moved to Core.'
 lifecycle: obsolete
+lifecycle_link: 'https://www.drupal.org/about/core/policies/core-change-policies/deprecated-and-obsolete-modules-and-themes#s-entity-reference'
 package: Field types
 version: VERSION
 hidden: true
diff --git a/core/modules/simpletest/simpletest.info.yml b/core/modules/simpletest/simpletest.info.yml
index fda052ad37353096cbbe7ce1284a30bf3fb5a6b1..72682600b3abdc8294faed237f9e06b92bc11100 100644
--- a/core/modules/simpletest/simpletest.info.yml
+++ b/core/modules/simpletest/simpletest.info.yml
@@ -2,6 +2,7 @@ name: Testing
 type: module
 description: 'Obsolete. SimpleTest has been removed from core.'
 lifecycle: obsolete
+lifecycle_link: 'https://www.drupal.org/about/core/policies/core-change-policies/deprecated-and-obsolete-modules-and-themes#s-simpletest'
 package: Core
 version: VERSION
 hidden: true
diff --git a/core/modules/system/tests/modules/system_status_obsolete_test/system_status_obsolete_test.info.yml b/core/modules/system/tests/modules/system_status_obsolete_test/system_status_obsolete_test.info.yml
index f4760df19956c3f33a64a6a74f8d91c08d593af4..3b648efd2f2bb56de2479241700e9e418d81ff8e 100644
--- a/core/modules/system/tests/modules/system_status_obsolete_test/system_status_obsolete_test.info.yml
+++ b/core/modules/system/tests/modules/system_status_obsolete_test/system_status_obsolete_test.info.yml
@@ -4,3 +4,4 @@ description: 'Support module for testing an obsolete module extension.'
 package: Testing
 version: VERSION
 lifecycle: obsolete
+lifecycle_link: 'https://i.giphy.com/media/100JPq1ylYXEti/giphy.webp'
diff --git a/core/tests/Drupal/Tests/Core/Extension/InfoParserUnitTest.php b/core/tests/Drupal/Tests/Core/Extension/InfoParserUnitTest.php
index aa3914e99697dad241468e6462adbdea2e333c6f..cfd3439baa5fe34157ee746b0bda5769cd0c391d 100644
--- a/core/tests/Drupal/Tests/Core/Extension/InfoParserUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/InfoParserUnitTest.php
@@ -710,6 +710,9 @@ public function testValidLifecycle($lifecycle, $expected) {
     if (!empty($lifecycle)) {
       $info .= "\nlifecycle: $lifecycle\n";
     }
+    if (in_array($lifecycle, [ExtensionLifecycle::DEPRECATED, ExtensionLifecycle::OBSOLETE], TRUE)) {
+      $info .= "\nlifecycle_link: http://example.com\n";
+    }
     vfsStream::setup('modules');
     $filename = "lifecycle-$lifecycle.info.yml";
     vfsStream::create([
@@ -798,4 +801,84 @@ public function providerInvalidLifecycle() {
     ];
   }
 
+  /**
+   * Tests an info file's lifecycle_link values.
+   *
+   * @covers ::parse
+   *
+   * @dataProvider providerLifecycleLink
+   */
+  public function testLifecycleLink($lifecycle, $lifecycle_link = NULL, $exception_message = NULL) {
+    $info = <<<INFO
+package: Core
+core: 8.x
+version: VERSION
+type: module
+name: Module for That
+lifecycle: $lifecycle
+INFO;
+    if (($lifecycle_link)) {
+      $info .= "\nlifecycle_link: $lifecycle_link\n";
+    }
+    vfsStream::setup('modules');
+    // Use a random file name to bypass the static caching in
+    // \Drupal\Core\Extension\InfoParser.
+    $random = mb_strtolower($this->randomMachineName());
+    $filename = "lifecycle-$random.info.yml";
+    vfsStream::create([
+      'fixtures' => [
+        $filename => $info,
+      ],
+    ]);
+    $path = vfsStream::url("modules/fixtures/$filename");
+    if ($exception_message) {
+      $this->expectException(InfoParserException::class);
+      $this->expectExceptionMessage(sprintf($exception_message, $path));
+    }
+    $info_values = $this->infoParser->parse($path);
+    $this->assertSame($lifecycle, $info_values[ExtensionLifecycle::LIFECYCLE_IDENTIFIER]);
+  }
+
+  /**
+   * Data provider for testLifecycleLink().
+   */
+  public function providerLifecycleLink() {
+    return [
+      'valid deprecated' => [
+        ExtensionLifecycle::DEPRECATED,
+        'http://example.com',
+      ],
+      'valid obsolete' => [
+        ExtensionLifecycle::OBSOLETE,
+        'http://example.com',
+      ],
+      'valid stable' => [
+        ExtensionLifecycle::STABLE,
+      ],
+      'valid experimental' => [
+        ExtensionLifecycle::EXPERIMENTAL,
+      ],
+      'missing deprecated' => [
+        ExtensionLifecycle::DEPRECATED,
+        NULL,
+        "Extension Module for That (%s) has 'lifecycle: deprecated' but is missing a 'lifecycle_link' entry.",
+      ],
+      'missing obsolete' => [
+        ExtensionLifecycle::OBSOLETE,
+        NULL,
+        "Extension Module for That (%s) has 'lifecycle: obsolete' but is missing a 'lifecycle_link' entry.",
+      ],
+      'invalid deprecated' => [
+        ExtensionLifecycle::DEPRECATED,
+        'look ma, not a url',
+        "Extension Module for That (%s) has a 'lifecycle_link' entry that is not a valid URL.",
+      ],
+      'invalid obsolete' => [
+        ExtensionLifecycle::OBSOLETE,
+        'I think you may find that this is also not a url',
+        "Extension Module for That (%s) has a 'lifecycle_link' entry that is not a valid URL.",
+      ],
+    ];
+  }
+
 }