diff --git a/core/modules/help/src/Attribute/HelpSection.php b/core/modules/help/src/Attribute/HelpSection.php
new file mode 100644
index 0000000000000000000000000000000000000000..17564b7df0e1c941494e0c9b8e28f49ccedb705c
--- /dev/null
+++ b/core/modules/help/src/Attribute/HelpSection.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\help\Attribute;
+
+use Drupal\Component\Plugin\Attribute\Plugin;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
+
+/**
+ * Defines a HelpSection attribute object for plugin discovery.
+ *
+ * Plugin Namespace: Plugin\HelpSection
+ *
+ * For a working example, see \Drupal\help\Plugin\HelpSection\HookHelpSection.
+ *
+ * @see \Drupal\help\HelpSectionPluginInterface
+ * @see \Drupal\help\Plugin\HelpSection\HelpSectionPluginBase
+ * @see \Drupal\help\HelpSectionManager
+ * @see hook_help_section_info_alter()
+ * @see plugin_api
+ */
+#[\Attribute(\Attribute::TARGET_CLASS)]
+class HelpSection extends Plugin {
+
+  /**
+   * Constructs a HelpSection attribute.
+   *
+   * @param string $id
+   *   The plugin ID.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup $title
+   *   The text to use as the title of the help page section.
+   * @param \Drupal\Core\StringTranslation\TranslatableMarkup|null $description
+   *   (optional) The description of the help page section.
+   * @param string|null $permission
+   *   (optional) The permission required to access the help page section.
+   *
+   *   Only set if this section needs its own permission, beyond the generic
+   *   'access help pages' permission needed to see the /admin/help
+   *   page itself.
+   * @param int|null $weight
+   *   (optional) The weight of the help page section.
+   * @param string|null $deriver
+   *   (optional) The deriver class.
+   *
+   *   The sections will be ordered by this weight on the help page.
+   */
+  public function __construct(
+    public readonly string $id,
+    public readonly TranslatableMarkup $title,
+    public readonly ?TranslatableMarkup $description = NULL,
+    public readonly ?string $permission = NULL,
+    public readonly ?int $weight = NULL,
+    public readonly ?string $deriver = NULL,
+  ) {}
+
+}
diff --git a/core/modules/help/src/HelpSectionManager.php b/core/modules/help/src/HelpSectionManager.php
index 1943ee056d48467bbe672bb3b4affe03c267f430..656ab14dc1998fd3a6492c52f06324a622b72bc5 100644
--- a/core/modules/help/src/HelpSectionManager.php
+++ b/core/modules/help/src/HelpSectionManager.php
@@ -3,6 +3,7 @@
 namespace Drupal\help;
 
 use Drupal\Component\Plugin\PluginManagerInterface;
+use Drupal\help\Attribute\HelpSection;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Plugin\DefaultPluginManager;
@@ -36,7 +37,7 @@ class HelpSectionManager extends DefaultPluginManager {
    *   The module handler for the alter hook.
    */
   public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
-    parent::__construct('Plugin/HelpSection', $namespaces, $module_handler, 'Drupal\help\HelpSectionPluginInterface', 'Drupal\help\Annotation\HelpSection');
+    parent::__construct('Plugin/HelpSection', $namespaces, $module_handler, 'Drupal\help\HelpSectionPluginInterface', HelpSection::class, 'Drupal\help\Annotation\HelpSection');
 
     $this->alterInfo('help_section_info');
     $this->setCacheBackend($cache_backend, 'help_section_plugins');
diff --git a/core/modules/help/src/Plugin/HelpSection/HelpTopicSection.php b/core/modules/help/src/Plugin/HelpSection/HelpTopicSection.php
index 6314ee535c4378f39ed9e3b9f214a335ee3acf72..e2395f56fb67fd37eaa962e17299e9774eee84f8 100644
--- a/core/modules/help/src/Plugin/HelpSection/HelpTopicSection.php
+++ b/core/modules/help/src/Plugin/HelpSection/HelpTopicSection.php
@@ -3,6 +3,8 @@
 namespace Drupal\help\Plugin\HelpSection;
 
 use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\help\Attribute\HelpSection;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\help\SearchableHelpInterface;
 use Drupal\help\HelpTopicPluginInterface;
 use Drupal\help\HelpTopicPluginManagerInterface;
@@ -18,17 +20,15 @@
 /**
  * Provides the help topics list section for the help page.
  *
- * @HelpSection(
- *   id = "help_topics",
- *   title = @Translation("Topics"),
- *   weight = -10,
- *   description = @Translation("Topics can be provided by modules or themes. Top-level help topics on your site:"),
- *   permission = "access help pages"
- * )
- *
  * @internal
  *   Plugin classes are internal.
  */
+#[HelpSection(
+  id: 'help_topics',
+  title: new TranslatableMarkup('Topics'),
+  description: new TranslatableMarkup('Topics can be provided by modules or themes. Top-level help topics on your site:'),
+  weight: -10
+)]
 class HelpTopicSection extends HelpSectionPluginBase implements ContainerFactoryPluginInterface, SearchableHelpInterface {
 
   /**
diff --git a/core/modules/help/src/Plugin/HelpSection/HookHelpSection.php b/core/modules/help/src/Plugin/HelpSection/HookHelpSection.php
index 1625c90463f89a0be8bc124e4b821bf7a924546e..9336d7fde4031a3beb3e65a8257fffc289c0f1ed 100644
--- a/core/modules/help/src/Plugin/HelpSection/HookHelpSection.php
+++ b/core/modules/help/src/Plugin/HelpSection/HookHelpSection.php
@@ -3,19 +3,20 @@
 namespace Drupal\help\Plugin\HelpSection;
 
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\Core\Link;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\help\Attribute\HelpSection;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Provides the module topics list section for the help page.
- *
- * @HelpSection(
- *   id = "hook_help",
- *   title = @Translation("Module overviews"),
- *   description = @Translation("Module overviews are provided by modules. Overviews available for your installed modules:"),
- * )
  */
+#[HelpSection(
+  id: 'hook_help',
+  title: new TranslatableMarkup('Module overviews'),
+  description: new TranslatableMarkup('Module overviews are provided by modules. Overviews available for your installed modules:')
+)]
 class HookHelpSection extends HelpSectionPluginBase implements ContainerFactoryPluginInterface {
 
   /**
diff --git a/core/modules/help/tests/modules/help_page_test/src/Plugin/HelpSection/EmptyHelpSection.php b/core/modules/help/tests/modules/help_page_test/src/Plugin/HelpSection/EmptyHelpSection.php
index db390285bbfdcf033e8f8191ec4fd64acea2e7f5..45480795756a086560cf499efa62f97321881848 100644
--- a/core/modules/help/tests/modules/help_page_test/src/Plugin/HelpSection/EmptyHelpSection.php
+++ b/core/modules/help/tests/modules/help_page_test/src/Plugin/HelpSection/EmptyHelpSection.php
@@ -2,17 +2,18 @@
 
 namespace Drupal\help_page_test\Plugin\HelpSection;
 
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\help\Plugin\HelpSection\HelpSectionPluginBase;
+use Drupal\help\Attribute\HelpSection;
 
 /**
  * Provides an empty section for the help page, for testing.
- *
- * @HelpSection(
- *   id = "empty_section",
- *   title = @Translation("Empty section"),
- *   description = @Translation("This description should appear."),
- * )
  */
+#[HelpSection(
+  id: 'empty_section',
+  title: new TranslatableMarkup('Empty section'),
+  description: new TranslatableMarkup('This description should appear.')
+)]
 class EmptyHelpSection extends HelpSectionPluginBase {
 
   /**
diff --git a/core/modules/help/tests/modules/help_topics_test/src/Plugin/HelpSection/TestHelpSection.php b/core/modules/help/tests/modules/help_topics_test/src/Plugin/HelpSection/TestHelpSection.php
index 9860221800cd5372aa375e295667ab967e76d615..731886e4fda4f03e6ca108d3447450cc286c7a43 100644
--- a/core/modules/help/tests/modules/help_topics_test/src/Plugin/HelpSection/TestHelpSection.php
+++ b/core/modules/help/tests/modules/help_topics_test/src/Plugin/HelpSection/TestHelpSection.php
@@ -7,20 +7,21 @@
 use Drupal\Core\Url;
 use Drupal\Core\Link;
 use Drupal\help\Plugin\HelpSection\HelpSectionPluginBase;
+use Drupal\help\Attribute\HelpSection;
+use Drupal\Core\StringTranslation\TranslatableMarkup;
 
 // cspell:ignore asdrsad barmm foomm sqruct wcsrefsdf sdeeeee
 
 /**
  * Provides a searchable help section for testing.
- *
- * @HelpSection(
- *   id = "help_topics_test",
- *   title = @Translation("Test section"),
- *   weight = 100,
- *   description = @Translation("For testing search"),
- *   permission = "access test help"
- * )
  */
+#[HelpSection(
+  id: 'help_topics_test',
+  title: new TranslatableMarkup('Test section'),
+  description: new TranslatableMarkup('For testing search'),
+  permission: 'access test help',
+  weight: 100
+)]
 class TestHelpSection extends HelpSectionPluginBase implements SearchableHelpInterface {
 
   /**