diff --git a/ee/app/assets/javascripts/api.js b/ee/app/assets/javascripts/api.js
index 4615b51bda413d8ab5049f14d102ee09de2b3cec..7863b15072243ccc8410f95a4051f63e94f3fc01 100644
--- a/ee/app/assets/javascripts/api.js
+++ b/ee/app/assets/javascripts/api.js
@@ -303,11 +303,6 @@ export default {
     return axios.post(url, params);
   },
 
-  fetchVulnerability(id, params) {
-    const url = Api.buildUrl(this.vulnerabilityPath).replace(':id', id);
-    return axios.get(url, params);
-  },
-
   changeVulnerabilityState(id, state) {
     const url = Api.buildUrl(this.vulnerabilityActionPath)
       .replace(':id', id)
diff --git a/ee/app/assets/javascripts/security_dashboard/graphql/header_vulnerability.graphql b/ee/app/assets/javascripts/security_dashboard/graphql/header_vulnerability.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..f7b602ee1ab50939894275bef152daee4c6db32d
--- /dev/null
+++ b/ee/app/assets/javascripts/security_dashboard/graphql/header_vulnerability.graphql
@@ -0,0 +1,18 @@
+query vulnerability($id: VulnerabilityID!) {
+  vulnerability(id: $id) {
+    state
+    confirmedAt
+    detectedAt
+    dismissedAt
+    resolvedAt
+    dismissedBy {
+      id
+    }
+    confirmedBy {
+      id
+    }
+    resolvedBy {
+      id
+    }
+  }
+}
diff --git a/ee/app/assets/javascripts/vulnerabilities/components/header.vue b/ee/app/assets/javascripts/vulnerabilities/components/header.vue
index 8c813103946f9f849d786d126190c8d54802d5c4..091a0043a986a152f49c64f675ab48250872077d 100644
--- a/ee/app/assets/javascripts/vulnerabilities/components/header.vue
+++ b/ee/app/assets/javascripts/vulnerabilities/components/header.vue
@@ -1,8 +1,7 @@
 <script>
 import { GlLoadingIcon, GlButton, GlBadge } from '@gitlab/ui';
-import Api from 'ee/api';
-import { CancelToken } from 'axios';
 import SplitButton from 'ee/vue_shared/security_reports/components/split_button.vue';
+import fetchHeaderVulnerabilityQuery from 'ee/security_dashboard/graphql/header_vulnerability.graphql';
 import vulnerabilityStateMutations from 'ee/security_dashboard/graphql/mutate_vulnerability_state';
 import axios from '~/lib/utils/axios_utils';
 import download from '~/lib/utils/downloader';
@@ -14,9 +13,13 @@ import UsersCache from '~/lib/utils/users_cache';
 import ResolutionAlert from './resolution_alert.vue';
 import VulnerabilityStateDropdown from './vulnerability_state_dropdown.vue';
 import StatusDescription from './status_description.vue';
-import { VULNERABILITY_STATE_OBJECTS, FEEDBACK_TYPES, HEADER_ACTION_BUTTONS } from '../constants';
-
-const gidPrefix = 'gid://gitlab/Vulnerability/';
+import { normalizeGraphQLVulnerability } from '../helpers';
+import {
+  VULNERABILITY_STATE_OBJECTS,
+  FEEDBACK_TYPES,
+  HEADER_ACTION_BUTTONS,
+  gidPrefix,
+} from '../constants';
 
 export default {
   name: 'VulnerabilityHeader',
@@ -47,7 +50,7 @@ export default {
       // prop leading to an error in the footer component.
       vulnerability: { ...this.initialVulnerability },
       user: undefined,
-      refreshVulnerabilitySource: undefined,
+      shouldRefreshVulnerability: false,
     };
   },
 
@@ -57,6 +60,38 @@ export default {
     detected: 'warning',
   },
 
+  apollo: {
+    vulnerability: {
+      query: fetchHeaderVulnerabilityQuery,
+      manual: true,
+      fetchPolicy: 'no-cache',
+      variables() {
+        return {
+          id: `${gidPrefix}${this.vulnerability.id}`,
+        };
+      },
+      result({ data: { vulnerability } }) {
+        this.shouldRefreshVulnerability = false;
+        this.isLoadingVulnerability = false;
+
+        this.vulnerability = {
+          ...this.vulnerability,
+          ...normalizeGraphQLVulnerability(vulnerability),
+        };
+      },
+      error() {
+        createFlash(
+          s__(
+            'VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later.',
+          ),
+        );
+      },
+      skip() {
+        return !this.shouldRefreshVulnerability;
+      },
+    },
+  },
+
   computed: {
     stateVariant() {
       return this.$options.badgeVariants[this.vulnerability.state] || 'neutral';
@@ -144,13 +179,10 @@ export default {
           variables: { id: `${gidPrefix}${this.vulnerability.id}`, ...payload },
         });
         const [queryName] = Object.keys(data);
-        const { vulnerability } = data[queryName];
-        vulnerability.id = vulnerability.id.replace(gidPrefix, '');
-        vulnerability.state = vulnerability.state.toLowerCase();
 
         this.vulnerability = {
           ...this.vulnerability,
-          ...vulnerability,
+          ...normalizeGraphQLVulnerability(data[queryName].vulnerability),
         };
 
         this.$emit('vulnerability-state-change');
@@ -207,34 +239,7 @@ export default {
     },
     refreshVulnerability() {
       this.isLoadingVulnerability = true;
-
-      // Cancel any pending API requests.
-      if (this.refreshVulnerabilitySource) {
-        this.refreshVulnerabilitySource.cancel();
-      }
-
-      this.refreshVulnerabilitySource = CancelToken.source();
-
-      Api.fetchVulnerability(this.vulnerability.id, {
-        cancelToken: this.refreshVulnerabilitySource.token,
-      })
-        .then(({ data }) => {
-          Object.assign(this.vulnerability, data);
-        })
-        .catch((e) => {
-          // Don't show an error message if the request was cancelled through the cancel token.
-          if (!axios.isCancel(e)) {
-            createFlash(
-              s__(
-                'VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later.',
-              ),
-            );
-          }
-        })
-        .finally(() => {
-          this.isLoadingVulnerability = false;
-          this.refreshVulnerabilitySource = undefined;
-        });
+      this.shouldRefreshVulnerability = true;
     },
   },
 };
diff --git a/ee/app/assets/javascripts/vulnerabilities/constants.js b/ee/app/assets/javascripts/vulnerabilities/constants.js
index b19b6abb08b3c73d456ff2b661e41a0ee24aa41f..2689d82fefbb0cd96eda96618922bcd2b5c4e184 100644
--- a/ee/app/assets/javascripts/vulnerabilities/constants.js
+++ b/ee/app/assets/javascripts/vulnerabilities/constants.js
@@ -6,6 +6,9 @@ import {
 
 const falsePositiveMessage = s__('VulnerabilityManagement|Will not fix or a false-positive');
 
+export const gidPrefix = 'gid://gitlab/Vulnerability/';
+export const uidPrefix = 'gid://gitlab/User/';
+
 export const VULNERABILITY_STATE_OBJECTS = {
   detected: {
     action: 'revert',
diff --git a/ee/app/assets/javascripts/vulnerabilities/helpers.js b/ee/app/assets/javascripts/vulnerabilities/helpers.js
index 8e08d0bcbf8935c869746de1701f3e432efc75d1..4e6e8bc3f31931e30956be707d766dbbcfda1554 100644
--- a/ee/app/assets/javascripts/vulnerabilities/helpers.js
+++ b/ee/app/assets/javascripts/vulnerabilities/helpers.js
@@ -1,5 +1,5 @@
 import { isAbsolute, isSafeURL } from '~/lib/utils/url_utility';
-import { REGEXES } from './constants';
+import { REGEXES, gidPrefix, uidPrefix } from './constants';
 
 // Get the issue in the format expected by the descendant components of related_issues_block.vue.
 export const getFormattedIssue = (issue) => ({
@@ -27,3 +27,28 @@ export const getAddRelatedIssueRequestParams = (reference, defaultProjectId) =>
 
   return { target_issue_iid: issueId, target_project_id: projectId };
 };
+
+export const normalizeGraphQLVulnerability = (vulnerability) => {
+  if (!vulnerability) {
+    return null;
+  }
+
+  const newVulnerability = { ...vulnerability };
+
+  if (vulnerability.id) {
+    newVulnerability.id = vulnerability.id.replace(gidPrefix, '');
+  }
+
+  if (vulnerability.state) {
+    newVulnerability.state = vulnerability.state.toLowerCase();
+  }
+
+  ['confirmed', 'resolved', 'dismissed'].forEach((state) => {
+    if (vulnerability[`${state}By`]?.id) {
+      newVulnerability[`${state}ById`] = vulnerability[`${state}By`].id.replace(uidPrefix, '');
+      delete newVulnerability[`${state}By`];
+    }
+  });
+
+  return newVulnerability;
+};
diff --git a/ee/spec/frontend/vulnerabilities/header_spec.js b/ee/spec/frontend/vulnerabilities/header_spec.js
index 932ba1e014f2c53c8964214a4837caa6a9e0c8e2..e3ad95269e70b86a716bb35b05970417f71d3240 100644
--- a/ee/spec/frontend/vulnerabilities/header_spec.js
+++ b/ee/spec/frontend/vulnerabilities/header_spec.js
@@ -9,6 +9,7 @@ import ResolutionAlert from 'ee/vulnerabilities/components/resolution_alert.vue'
 import StatusDescription from 'ee/vulnerabilities/components/status_description.vue';
 import VulnerabilityStateDropdown from 'ee/vulnerabilities/components/vulnerability_state_dropdown.vue';
 import vulnerabilityStateMutations from 'ee/security_dashboard/graphql/mutate_vulnerability_state';
+import fetchHeaderVulnerabilityQuery from 'ee/security_dashboard/graphql/header_vulnerability.graphql';
 import { FEEDBACK_TYPES, VULNERABILITY_STATE_OBJECTS } from 'ee/vulnerabilities/constants';
 import UsersMockHelper from 'helpers/user_mock_data_helper';
 import waitForPromises from 'helpers/wait_for_promises';
@@ -418,4 +419,63 @@ describe('Vulnerability Header', () => {
       });
     });
   });
+
+  describe('refresh vulnerability', () => {
+    describe('on success', () => {
+      beforeEach(() => {
+        const apolloProvider = createApolloProvider([
+          fetchHeaderVulnerabilityQuery,
+          jest.fn().mockResolvedValue({
+            data: {
+              errors: [],
+              vulnerability: {
+                id: 'gid://gitlab/Vulnerability/54',
+                [`resolvedAt`]: '2020-09-16T11:13:26Z',
+                state: 'RESOLVED',
+              },
+            },
+          }),
+        ]);
+
+        createWrapper({
+          apolloProvider,
+          vulnerability: getVulnerability({}),
+        });
+      });
+
+      it('fetches the vulnerability when refreshVulnerability method is called', async () => {
+        expect(findBadge().text()).toBe('detected');
+        wrapper.vm.refreshVulnerability();
+        await waitForPromises();
+        expect(findBadge().text()).toBe('resolved');
+      });
+    });
+
+    describe('on failure', () => {
+      beforeEach(() => {
+        const apolloProvider = createApolloProvider([
+          fetchHeaderVulnerabilityQuery,
+          jest.fn().mockRejectedValue({
+            data: {
+              errors: [{ message: 'something went wrong while fetching the vulnerability' }],
+              vulnerability: null,
+            },
+          }),
+        ]);
+
+        createWrapper({
+          apolloProvider,
+          vulnerability: getVulnerability({}),
+        });
+      });
+
+      it('calls createFlash', async () => {
+        expect(findBadge().text()).toBe('detected');
+        wrapper.vm.refreshVulnerability();
+        await waitForPromises();
+        expect(findBadge().text()).toBe('detected');
+        expect(createFlash).toHaveBeenCalledTimes(1);
+      });
+    });
+  });
 });
diff --git a/ee/spec/frontend/vulnerabilities/helpers_spec.js b/ee/spec/frontend/vulnerabilities/helpers_spec.js
index f81e666d9355de2d0b2c879f904a94ce5abc0b8d..9d89a65351ce741bcf243d48473f9e4bbaca7483 100644
--- a/ee/spec/frontend/vulnerabilities/helpers_spec.js
+++ b/ee/spec/frontend/vulnerabilities/helpers_spec.js
@@ -1,4 +1,8 @@
-import { getFormattedIssue, getAddRelatedIssueRequestParams } from 'ee/vulnerabilities/helpers';
+import {
+  getFormattedIssue,
+  getAddRelatedIssueRequestParams,
+  normalizeGraphQLVulnerability,
+} from 'ee/vulnerabilities/helpers';
 
 describe('Vulnerabilities helpers', () => {
   describe('getFormattedIssue', () => {
@@ -37,4 +41,28 @@ describe('Vulnerabilities helpers', () => {
       },
     );
   });
+
+  describe('normalizeGraphQLVulnerability', () => {
+    it('returns null when vulnerability is null', () => {
+      expect(normalizeGraphQLVulnerability(null)).toBe(null);
+    });
+
+    it('normalizes the GraphQL response when the vulnerability is not null', () => {
+      expect(
+        normalizeGraphQLVulnerability({
+          confirmedBy: { id: 'gid://gitlab/User/16' },
+          resolvedBy: { id: 'gid://gitlab/User/16' },
+          dismissedBy: { id: 'gid://gitlab/User/16' },
+          state: 'DISMISSED',
+          id: 'gid://gitlab/Vulnerability/54',
+        }),
+      ).toEqual({
+        confirmedById: '16',
+        resolvedById: '16',
+        dismissedById: '16',
+        state: 'dismissed',
+        id: '54',
+      });
+    });
+  });
 });