diff --git a/ee/app/assets/javascripts/security_orchestration/components/group_projects_dropdown.vue b/ee/app/assets/javascripts/security_orchestration/components/group_projects_dropdown.vue
index 8d0ac420619581809d38fa8096c0a0faeada52b1..c9704afed19599caf0e0fcdcb2011deb8f0c028c 100644
--- a/ee/app/assets/javascripts/security_orchestration/components/group_projects_dropdown.vue
+++ b/ee/app/assets/javascripts/security_orchestration/components/group_projects_dropdown.vue
@@ -10,6 +10,8 @@ import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
 export default {
   i18n: {
     projectDropdownHeader: __('Select projects'),
+    selectAllLabel: __('Select all'),
+    clearAllLabel: __('Clear all'),
   },
   name: 'GroupProjectsDropdown',
   components: {
@@ -84,11 +86,15 @@ export default {
         selected: this.formattedSelectedProjectsIds,
         items: this.projectItems,
         itemTypeName: __('projects'),
+        useAllSelected: !this.hasNextPage,
       });
     },
     loading() {
       return this.$apollo.queries.projects.loading;
     },
+    hasNextPage() {
+      return this.projectsPageInfo.hasNextPage;
+    },
     projectItems() {
       return this.projects?.reduce((acc, { id, name }) => {
         acc[id] = name;
@@ -101,6 +107,15 @@ export default {
     projectsIds() {
       return this.projects.map(({ id }) => id);
     },
+    resetButtonLabel() {
+      return this.multiple ? this.$options.i18n.clearAllLabel : '';
+    },
+    category() {
+      return this.state ? 'primary' : 'secondary';
+    },
+    variant() {
+      return this.state ? 'default' : 'danger';
+    },
   },
   created() {
     this.debouncedSearch = debounce(this.setSearchTerm, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
@@ -148,12 +163,15 @@ export default {
     is-check-centered
     searchable
     fluid-width
-    :toggle-class="{ 'gl-inset-border-1-red-500!': !state }"
+    :category="category"
+    :variant="variant"
     :multiple="multiple"
     :loading="loading"
     :header-text="$options.i18n.projectDropdownHeader"
-    :infinite-scroll="projectsPageInfo.hasNextPage"
+    :infinite-scroll="hasNextPage"
     :infinite-scroll-loading="loading"
+    :reset-button-label="resetButtonLabel"
+    :show-select-all-button-label="$options.i18n.selectAllLabel"
     :searching="loading"
     :selected="existingFormattedSelectedProjectsIds"
     :placement="placement"
@@ -161,6 +179,8 @@ export default {
     :toggle-text="dropdownPlaceholder"
     @bottom-reached="fetchMoreGroupProjects"
     @search="debouncedSearch"
+    @reset="selectProjects([])"
     @select="selectProjects"
+    @select-all="selectProjects(projectsIds)"
   />
 </template>
diff --git a/ee/spec/frontend/security_orchestration/components/group_projects_dropdown_spec.js b/ee/spec/frontend/security_orchestration/components/group_projects_dropdown_spec.js
index 41960de2846fa34821ce4bf6dc911bc65e6be77e..a279de29fb65390f6582f1850f85e8dfd0992049 100644
--- a/ee/spec/frontend/security_orchestration/components/group_projects_dropdown_spec.js
+++ b/ee/spec/frontend/security_orchestration/components/group_projects_dropdown_spec.js
@@ -191,6 +191,26 @@ describe('GroupProjectsDropdown', () => {
         expect(requestHandlers.getGroupProjects).toHaveBeenCalledTimes(2);
       });
 
+      it.each`
+        hasNextPage | expectedText
+        ${true}     | ${'1 +1 more'}
+        ${false}    | ${'All projects'}
+      `(
+        'selects all projects only when all projects loaded',
+        async ({ hasNextPage, expectedText }) => {
+          createComponent({
+            propsData: {
+              selected: defaultNodesIds,
+            },
+            handlers: mockApolloHandlers(defaultNodes, hasNextPage),
+          });
+
+          await waitForPromises();
+
+          expect(findDropdown().props('toggleText')).toBe(expectedText);
+        },
+      );
+
       describe('when the fetch query throws an error', () => {
         it('emits an error event', async () => {
           createComponent({
@@ -231,4 +251,44 @@ describe('GroupProjectsDropdown', () => {
       expect(findDropdown().props('selected')).toEqual(defaultNodesIds);
     });
   });
+
+  describe('validation', () => {
+    it('renders default dropdown when validation passes', () => {
+      createComponent({
+        propsData: {
+          state: true,
+        },
+      });
+
+      expect(findDropdown().props('variant')).toEqual('default');
+      expect(findDropdown().props('category')).toEqual('primary');
+    });
+
+    it('renders danger dropdown when validation passes', () => {
+      createComponent();
+
+      expect(findDropdown().props('variant')).toEqual('danger');
+      expect(findDropdown().props('category')).toEqual('secondary');
+    });
+  });
+
+  describe('select all', () => {
+    it('selects all projects', async () => {
+      createComponent();
+      await waitForPromises();
+
+      findDropdown().vm.$emit('select-all');
+
+      expect(wrapper.emitted('select')).toEqual([[defaultNodes]]);
+    });
+
+    it('resets all projects', async () => {
+      createComponent();
+      await waitForPromises();
+
+      findDropdown().vm.$emit('reset');
+
+      expect(wrapper.emitted('select')).toEqual([[[]]]);
+    });
+  });
 });