diff --git a/images/blue-security-shield-icon.svg b/images/blue-security-shield-icon.svg
index 1814c71ab1960c00bb8e670b6675bb391d607313..baec222292ce00d581ceb75010827e8ea2c80d38 100644
--- a/images/blue-security-shield-icon.svg
+++ b/images/blue-security-shield-icon.svg
@@ -1,4 +1,4 @@
-<svg width="31" height="31" viewBox="0 0 31 31" fill="none" xmlns="http://www.w3.org/2000/svg">
+<svg width="31" height="31" viewBox="3 4 25 23" fill="none" xmlns="http://www.w3.org/2000/svg">
     <path d="M24.2438 7.82616L16.2878 4.41643C15.7847 4.20081 15.2152 4.20081 14.7121 4.41643L6.75603 7.82616C5.9368 8.17726 5.44876 9.0281 5.55932 9.91252L6.46397 17.1497C6.68412 18.9109 7.56509 20.5228 8.92862 21.659L14.2196 26.0681C14.9612 26.6862 16.0386 26.6862 16.7803 26.0681L22.0712 21.659C23.4347 20.5228 24.3157 18.9109 24.5359 17.1497L25.4405 9.91252C25.5511 9.0281 25.063 8.17726 24.2438 7.82616Z" stroke="#003CC5" stroke-width="2" stroke-linecap="round"/>
     <path d="M11.6251 15.5L15.0688 18.9437C15.2919 19.1668 15.6634 19.1301 15.8384 18.8675L20.6667 11.625" stroke="#003CC5" stroke-width="2" stroke-linecap="round"/>
 </svg>
\ No newline at end of file
diff --git a/images/green-maintained-wrench-icon.svg b/images/green-maintained-wrench-icon.svg
deleted file mode 100644
index d584928f1d0e4b83d1754e732bf298359462b668..0000000000000000000000000000000000000000
--- a/images/green-maintained-wrench-icon.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<svg width="31" height="31" viewBox="-5 -3 31 31" fill="none" xmlns="http://www.w3.org/2000/svg">
-    <path d="M19.7856 4.65941L11.8295 1.24968C11.3264 1.03406 10.7569 1.03406 10.2538 1.24968L2.29778 4.65941C1.47855 5.01051 0.990512 5.86135 1.10106 6.74577L2.00572 13.983C2.22587 15.7442 3.10684 17.356 4.47037 18.4923L9.7613 22.9014C10.503 23.5195 11.5803 23.5195 12.322 22.9014L17.613 18.4923C18.9765 17.356 19.8575 15.7442 20.0776 13.983L20.9823 6.74577C21.0928 5.86135 20.6048 5.01051 19.7856 4.65941Z"
-          stroke="#71B43D" stroke-width="2" stroke-linecap="round"/>
-    <path d="M8.11154 10.9899L7.34928 11.6372L7.88422 12.2672L8.60366 11.8605L8.11154 10.9899ZM11.6207 9.00614L12.1129 9.87667L12.8539 9.45775L12.5587 8.65935L11.6207 9.00614ZM13.2092 18.0066C13.4792 18.4883 14.0887 18.6599 14.5704 18.3899C15.0522 18.1198 15.2238 17.5104 14.9537 17.0286L13.2092 18.0066ZM5.57218 7.16219C5.40773 7.64804 5.34215 8.11967 5.39734 8.58696C5.45262 9.05488 5.62146 9.45431 5.8345 9.80386C6.04064 10.1421 6.3001 10.4518 6.54986 10.7351C6.81997 11.0414 7.06271 11.2997 7.34928 11.6372L8.87379 10.3427C8.57775 9.99404 8.26679 9.65818 8.04992 9.41225C7.81271 9.14325 7.6519 8.94281 7.54229 8.76297C7.43959 8.59446 7.3972 8.468 7.38353 8.35234C7.3698 8.23605 7.37758 8.06639 7.4666 7.80341L5.57218 7.16219ZM12.5587 8.65935C12.4279 8.3056 12.3295 7.96118 12.2183 7.58989C12.1136 7.24024 11.9914 6.84446 11.8225 6.48856C11.65 6.12512 11.3978 5.73392 10.9911 5.43968C10.5709 5.13569 10.0753 4.99929 9.53106 4.99669L9.52149 6.99666C9.72727 6.99765 9.79608 7.04363 9.81883 7.06008C9.85505 7.08629 9.92429 7.15361 10.0156 7.34604C10.1105 7.54602 10.1945 7.80345 10.3024 8.16366C10.4038 8.50222 10.5243 8.92429 10.6828 9.35293L12.5587 8.65935ZM8.60366 11.8605L10.3583 10.8686L9.37402 9.12752L7.61942 10.1194L8.60366 11.8605ZM10.3583 10.8686L12.1129 9.87667L11.1286 8.13561L9.37402 9.12752L10.3583 10.8686ZM8.99385 10.487L13.2092 18.0066L14.9537 17.0286L10.7384 9.50906L8.99385 10.487Z"
-          fill="#71B43D"/>
-    <mask id="path-3-inside-1_137_4246" fill="white">
-        <path d="M14 16.5C14 16.7761 13.7761 17 13.5 17C13.2239 17 13 16.7761 13 16.5C13 16.2239 13.2239 16 13.5 16C13.7761 16 14 16.2239 14 16.5Z"/>
-    </mask>
-    <path d="M14 16.5C14 16.7761 13.7761 17 13.5 17C13.2239 17 13 16.7761 13 16.5C13 16.2239 13.2239 16 13.5 16C13.7761 16 14 16.2239 14 16.5Z"
-          fill="white"/>
-    <path d="M13 16.5C13 16.2239 13.2239 16 13.5 16V18C14.3284 18 15 17.3284 15 16.5H13ZM13.5 16C13.7761 16 14 16.2239 14 16.5H12C12 17.3284 12.6716 18 13.5 18V16ZM14 16.5C14 16.7761 13.7761 17 13.5 17V15C12.6716 15 12 15.6716 12 16.5H14ZM13.5 17C13.2239 17 13 16.7761 13 16.5H15C15 15.6716 14.3284 15 13.5 15V17Z"
-          fill="#71B43D" mask="url(#path-3-inside-1_137_4246)"/>
-</svg>
\ No newline at end of file
diff --git a/images/triangle-alert.svg b/images/triangle-alert.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a8c0d3a0bc76a4953199a30fef006338ce5386b9
--- /dev/null
+++ b/images/triangle-alert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="22.610355mm" height="25.777401mm" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <g><path d="M 40 8 L 5 70 L 75 70 L 40 8 Z" style="stroke-width: 10; stroke-linejoin: round; stroke: rgb(255, 124, 58); fill: rgb(255, 124, 58);"/></g>
+  <g><path d="m 43.957714,33.658331 q 0,4.98 -0.36,9.12 -0.36,4.14 -0.9,8.34 l -5.16,0 q -0.6,-4.2 -0.96,-8.34 -0.36,-4.2 -0.36,-9.12 l 0,-11.16 7.74,0 0,11.16 z m 0.9,26.46 q 0,2.1 -1.38,3.42 -1.38,1.32 -3.42,1.32 -1.98,0 -3.42,-1.32 -1.38,-1.32 -1.38,-3.42 0,-2.1 1.38,-3.42 1.44,-1.38 3.42,-1.38 2.04,0 3.42,1.38 1.38,1.32 1.38,3.42 z" style="fill: rgb(255, 255, 255);"/></g>
+</svg>
diff --git a/src/Plugin/ProjectBrowserSource/MockDrupalDotOrg.php b/src/Plugin/ProjectBrowserSource/MockDrupalDotOrg.php
index f0bb4187d2975fe536f2ed075ab87e7b0af80635..416831f83c7ad23340d9dd9d713072d2db8e416c 100644
--- a/src/Plugin/ProjectBrowserSource/MockDrupalDotOrg.php
+++ b/src/Plugin/ProjectBrowserSource/MockDrupalDotOrg.php
@@ -4,6 +4,7 @@ namespace Drupal\project_browser\Plugin\ProjectBrowserSource;
 
 use Composer\Semver\Semver;
 use Drupal\Component\Serialization\Json;
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\State\StateInterface;
@@ -79,6 +80,13 @@ class MockDrupalDotOrg extends ProjectBrowserSourceBase implements ContainerFact
    */
   protected $state;
 
+  /**
+   * ProjectBrowser cache bin.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $cacheBin;
+
   /**
    * Constructs a MockDrupalDotOrg object.
    *
@@ -96,13 +104,16 @@ class MockDrupalDotOrg extends ProjectBrowserSourceBase implements ContainerFact
    *   A Guzzle client object.
    * @param \Drupal\Core\State\StateInterface $state
    *   The state object.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_bin
+   *   The cache bin.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, LoggerInterface $logger, Connection $database, ClientInterface $http_client, StateInterface $state) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, LoggerInterface $logger, Connection $database, ClientInterface $http_client, StateInterface $state, CacheBackendInterface $cache_bin) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
     $this->logger = $logger;
     $this->database = $database;
     $this->httpClient = $http_client;
     $this->state = $state;
+    $this->cacheBin = $cache_bin;
   }
 
   /**
@@ -117,32 +128,55 @@ class MockDrupalDotOrg extends ProjectBrowserSourceBase implements ContainerFact
       $container->get('database'),
       $container->get('http_client'),
       $container->get('state'),
+      $container->get('cache.project_browser'),
     );
   }
 
+  /**
+   * Gets status vocabulary info from the Drupal.org json endpoint.
+   *
+   * @param int $taxonomy_id
+   *   The id of the taxonomy being retrieved.
+   *
+   * @return array|array[]
+   *   An array with the term id, name and description.
+   *
+   * @throws \GuzzleHttp\Exception\GuzzleException
+   *   Thrown if request is unsuccessful.
+   */
+  protected function getStatuses(int $taxonomy_id) {
+    $cached_statuses = $this->cacheBin->get("MockDrupalDotOrg:taxonomy_$taxonomy_id");
+    if ($cached_statuses) {
+      return $cached_statuses->data;
+    }
+    $url = "https://www.drupal.org/api-d7/taxonomy_term.json?vocabulary=$taxonomy_id";
+    $response = \Drupal::httpClient()->request('GET', $url);
+    if ($response->getStatusCode() !== 200) {
+      throw new \RuntimeException("Request to $url failed, returned {$response->getStatusCode()} with reason: {$response->getReasonPhrase()}");
+    }
+    $body = Json::decode($response->getBody()->getContents());
+    $list = $body['list'];
+    $list = array_map(function ($item) {
+      $item['id'] = $item['tid'];
+      return array_intersect_key($item, array_flip(['id', 'name', 'description']));
+    }, $list);
+    $this->cacheBin->set("MockDrupalDotOrg:taxonomy_$taxonomy_id", $list);
+
+    return $list;
+  }
+
   /**
    * {@inheritdoc}
    */
   public function getDevelopmentStatuses(): array {
-    return [
-      ['id' => 9988, 'name' => 'Active'],
-      ['id' => 13030, 'name' => 'Maintenance Only'],
-      ['id' => 16538, 'name' => 'No Further Development'],
-      ['id' => 9994, 'name' => 'Obsolete'],
-    ];
+    return $this->getStatuses(46);
   }
 
   /**
    * {@inheritdoc}
    */
   public function getMaintenanceStatuses(): array {
-    return [
-      ['id' => 13028, 'name' => 'Actively maintained'],
-      ['id' => 19370, 'name' => 'Minimal'],
-      ['id' => 9990, 'name' => 'Seeking co-maintainer'],
-      ['id' => 9992, 'name' => 'Seeking new maintainer'],
-      ['id' => 13032, 'name' => 'Unsupported'],
-    ];
+    return $this->getStatuses(44);
   }
 
   /**
@@ -394,6 +428,7 @@ class MockDrupalDotOrg extends ProjectBrowserSourceBase implements ContainerFact
         $project['is_covered'] = $this->projectIsCovered($project);
         $project['is_active'] = $this->projectIsActive($project);
         $project['is_maintained'] = $this->projectIsMaintained($project);
+        $project['warnings'] = $this->getWarnings($project);
 
         $returned_list[] = new Project($project);
       }
@@ -792,4 +827,34 @@ class MockDrupalDotOrg extends ProjectBrowserSourceBase implements ContainerFact
     return FALSE;
   }
 
+  /**
+   * Determines warning messages based on development and maintenance status.
+   *
+   * @param $project
+   *   A project array.
+   *
+   * @return string[]
+   *   An array of warning messages.
+   */
+  protected function getWarnings($project) {
+    // This is based on logic from Drupal.org.
+    // @see https://git.drupalcode.org/project/drupalorg/-/blob/e31465608d1380345834/drupalorg_project/drupalorg_project.module
+    $warnings = [];
+    $merged_vocabularies = array_merge($this->getDevelopmentStatuses(), $this->getMaintenanceStatuses());
+    $statuses = array_column($merged_vocabularies, 'description', 'id');
+    foreach (['taxonomy_vocabulary_44', 'taxonomy_vocabulary_46'] as $field) {
+      // Maintenance status is not Actively maintained and Development status is
+      // not Under active development.
+      $id = $project[$field]['id'] ?? FALSE;
+      if ($id && !in_array($id, [13028, 9988])) {
+        // Maintenance status is Abandoned, or Development status is No further
+        // development or Obsolete.
+        if (in_array($id, [13032, 16538, 9994])) {
+          $warnings[] = $statuses[$id];
+        }
+      }
+    }
+    return $warnings;
+  }
+
 }
diff --git a/src/ProjectBrowser/Project.php b/src/ProjectBrowser/Project.php
index f6c82252627890dd66713e01359a959bd82a426e..215bcb44cadebedbd7ccae9115bc8ef641e1f809 100644
--- a/src/ProjectBrowser/Project.php
+++ b/src/ProjectBrowser/Project.php
@@ -49,6 +49,9 @@ class Project implements ProjectInterface {
       $this->setIsCovered($project['is_covered']);
       $this->setIsMaintained($project['is_maintained']);
       $this->setIsCompatible($project['is_compatible']);
+      if (isset($project['warnings'])) {
+        $this->setWarnings($project['warnings']);
+      }
     }
   }
 
@@ -212,4 +215,11 @@ class Project implements ProjectInterface {
     $this->is_compatible = $compatible;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function setWarnings(array $warnings) {
+    $this->warnings = $warnings;
+  }
+
 }
diff --git a/src/ProjectBrowser/ProjectInterface.php b/src/ProjectBrowser/ProjectInterface.php
index 9aef6c4863a8c1b2c015e1c92773c697260c50eb..30c2a24acaec00408bc524b2bf56fee2a5deea54 100644
--- a/src/ProjectBrowser/ProjectInterface.php
+++ b/src/ProjectBrowser/ProjectInterface.php
@@ -129,4 +129,12 @@ interface ProjectInterface {
    */
   public function setIsCompatible(bool $compatible);
 
+  /**
+   * Warnings related to installing a given module.
+   *
+   * @param string[] $warnings
+   *   Warnings about the module to present the the user.
+   */
+  public function setWarnings(array $warnings);
+
 }
diff --git a/sveltejs/public/build/bundle.css b/sveltejs/public/build/bundle.css
index 01dafd4fb5ddd44f5070fd8b71a403b6745f35f5..2f565a4f6c9d2675d44df3243c1ab2cf5cc16dca 100644
Binary files a/sveltejs/public/build/bundle.css and b/sveltejs/public/build/bundle.css differ
diff --git a/sveltejs/public/build/bundle.js b/sveltejs/public/build/bundle.js
index dae643346047efcf48e660a8cbf6310321852382..1e46d70904e370ed15b990a15853a5328a004ca2 100644
Binary files a/sveltejs/public/build/bundle.js and b/sveltejs/public/build/bundle.js differ
diff --git a/sveltejs/public/build/bundle.js.map b/sveltejs/public/build/bundle.js.map
index 1165afb6ee55e6f3c8e4cc48586e706f9b1e83e7..cade11f98b3d0b3ba07c685efcbcf3d768419e94 100644
Binary files a/sveltejs/public/build/bundle.js.map and b/sveltejs/public/build/bundle.js.map differ
diff --git a/sveltejs/src/Project/Project.svelte b/sveltejs/src/Project/Project.svelte
index b06ae36361a62fc1f416e85313e4fea3307a382b..11e38956472367d403c8495d2338dee3e701057b 100644
--- a/sveltejs/src/Project/Project.svelte
+++ b/sveltejs/src/Project/Project.svelte
@@ -5,10 +5,8 @@
   import ActionButton from './ActionButton.svelte';
   import Image from './Image.svelte';
   import Categories from './Categories.svelte';
-  import SecurityCoverage from './SecurityCoverage.svelte';
-  import MaintainedIcon from './MaintainedIcon.svelte';
 
-  const { drupalSettings } = window;
+  const { drupalSettings, Drupal } = window;
 </script>
 
 <li class="project {toggleView.toLowerCase()}">
@@ -32,9 +30,39 @@
       />
     </div>
   </div>
-  <div class="icons">
-    <SecurityCoverage coverage={project.is_covered} />
-    <MaintainedIcon maintained={project.is_maintained} />
+  <div
+    class="icons"
+    class:warnings={project.warnings && project.warnings.length > 0}
+  >
+    {#if project.is_covered}
+      <span>
+        <img
+          src="{drupalSettings.project_browser.origin_url}/{drupalSettings
+            .project_browser.module_path}/images/blue-security-shield-icon.svg"
+          alt=""
+          title={Drupal.t('Covered by Drupal Security Team')}
+          class="project-status-icon"
+        />
+        <!-- Show the security policy description if it is accompanied by warnings,
+             since those also have descriptions.  -->
+        {#if project.warnings && project.warnings.length > 0}
+          <small>{Drupal.t('Covered by the security advisory policy')}</small>
+        {/if}
+      </span>
+    {/if}
+    {#if project.warnings && project.warnings.length > 0}
+      {#each project.warnings as warning}
+        <span>
+          <img
+            src="{drupalSettings.project_browser.origin_url}/{drupalSettings
+              .project_browser.module_path}/images/triangle-alert.svg"
+            alt=""
+            class="project-status-icon"
+          />
+          <small>{@html warning}</small>
+        </span>
+      {/each}
+    {/if}
     {#if toggleView === 'List'}
       <div class="container">
         <div class="image">
@@ -49,8 +77,17 @@
         </div>
       </div>
     {/if}
-    <ActionButton {project} />
+    <!--If there are no warnings, there is space to include the action button
+        in the icons container -->
+    {#if !project.warnings || project.warnings.length === 0}
+      <ActionButton {project} />
+    {/if}
   </div>
+  <!--If there are warnings, the action button needs to be moved out of the
+      icons container to provide space for the warning descriptions. -->
+  {#if project.warnings && project.warnings.length > 0}
+    <ActionButton {project} />
+  {/if}
 </li>
 
 <style>
@@ -163,9 +200,33 @@
     display: flex;
     padding: 1em 1em 1em 0;
   }
+  .icons :global(p) {
+    display: inline;
+  }
+  .icons.warnings {
+    display: block;
+  }
+  .icons.warnings span {
+    display: list-item;
+  }
+  .icons.warnings img {
+    display: inline;
+    width: 1.2rem;
+    position: relative;
+    bottom: -0.25rem;
+  }
+  .warnings + :global(.action) {
+    margin-right: 1em;
+    margin-bottom: 1em;
+  }
   .container {
     display: flex;
     align-items: center;
     justify-content: center;
   }
+  .project-status-icon {
+    width: 2.4em;
+    margin-right: 0.5em;
+    display: block;
+  }
 </style>
diff --git a/sveltejs/src/Search.svelte b/sveltejs/src/Search.svelte
index 9337e207ceb25aa5214bbe048c41d708510e3d7d..2cf79d33d6a7704808581080222d9c2847df8699 100644
--- a/sveltejs/src/Search.svelte
+++ b/sveltejs/src/Search.svelte
@@ -328,15 +328,6 @@
             for={`maintenanceStatus${id}`}
           >
             {label}
-            {#if id === ACTIVELY_MAINTAINED_ID}
-              <img
-                class="small-icons"
-                id="actively-maintained"
-                src="/{drupalSettings.project_browser
-                  .module_path}/images/green-maintained-wrench-icon.svg"
-                alt=""
-              />
-            {/if}
           </label>
         </FilterGroup>
         <FilterGroup
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php
index 558c6ea82d58266b0b0c51418ac9726d07c0bce9..96ab4f05e05691354d60b35163c1547458446fe8 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php
@@ -51,10 +51,9 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $assert_session = $this->assertSession();
 
     $assert_session->waitForElementVisible('css', '#project-browser .project');
-    $titles = array_map(function ($element) {
-      return $element->getText();
-    }, $page->findAll('css', '#project-browser .project__title'));
-    $this->assertSame($project_titles, $titles);
+    foreach ($project_titles as $key => $title) {
+      $this->assertEquals($title, $page->findAll('css', '#project-browser .project__title')[$key]->getText());
+    }
   }
 
   /**
@@ -147,6 +146,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $page->find('css', '#67')->click();
     // Click 'Commerce/Advertising' checkbox.
     $page->find('css', '#55')->click();
+
     $module_category_media_filter_selector = 'p.filters-applied:nth-child(3)';
     $module_category_media_filter_element = $page->find('css', $module_category_media_filter_selector);
     // Make sure the 'Media' module category filter is applied.