diff --git a/ee/app/assets/javascripts/security_dashboard/components/shared/filtered_search/tokens/severity_token.vue b/ee/app/assets/javascripts/security_dashboard/components/shared/filtered_search/tokens/severity_token.vue
index 8f0dc73794218198179700ad1a688efdc349e56e..3e0c64b6c0716b46c42c7f1f24b3077050a63f84 100644
--- a/ee/app/assets/javascripts/security_dashboard/components/shared/filtered_search/tokens/severity_token.vue
+++ b/ee/app/assets/javascripts/security_dashboard/components/shared/filtered_search/tokens/severity_token.vue
@@ -3,13 +3,20 @@ import { GlIcon, GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitl
 import { SEVERITY_LEVELS } from 'ee/security_dashboard/store/constants';
 import { getSelectedOptionsText } from '~/lib/utils/listbox_helpers';
 import { s__ } from '~/locale';
+import QuerystringSync from '../../filters/querystring_sync.vue';
 import { ALL_ID as ALL_SEVERITIES_VALUE } from '../../filters/constants';
+import eventHub from '../event_hub';
+
+const VALID_IDS = Object.entries(SEVERITY_LEVELS).map(([id]) => id.toUpperCase());
 
 export default {
+  VALID_IDS,
+
   components: {
     GlIcon,
     GlFilteredSearchToken,
     GlFilteredSearchSuggestion,
+    QuerystringSync,
   },
   props: {
     config: {
@@ -28,7 +35,7 @@ export default {
   },
   data() {
     return {
-      selectedSeverities: [ALL_SEVERITIES_VALUE],
+      selectedSeverities: this.value.data || [ALL_SEVERITIES_VALUE],
     };
   },
   computed: {
@@ -49,6 +56,26 @@ export default {
     },
   },
   methods: {
+    emitFiltersChanged() {
+      eventHub.$emit('filters-changed', {
+        severity: this.selectedSeverities.filter((value) => value !== ALL_SEVERITIES_VALUE),
+      });
+    },
+    resetSelected() {
+      this.selectedSeverities = [ALL_SEVERITIES_VALUE];
+      this.emitFiltersChanged();
+    },
+    updateSelectedFromQS(values) {
+      // This happens when we clear the token and re-select `Severity`
+      // to open the dropdown. At that stage we simply want to wait
+      // for the user to select new severities.
+      if (!values.length) {
+        return;
+      }
+
+      this.selectedSeverities = values;
+      this.emitFiltersChanged();
+    },
     toggleSelected(selectedValue) {
       const allSeveritiesSelected = selectedValue === ALL_SEVERITIES_VALUE;
 
@@ -84,33 +111,42 @@ export default {
 </script>
 
 <template>
-  <gl-filtered-search-token
-    :config="config"
-    v-bind="{ ...$props, ...$attrs }"
-    :multi-select-values="selectedSeverities"
-    :value="tokenValue"
-    v-on="$listeners"
-    @select="toggleSelected"
+  <querystring-sync
+    querystring-key="severity"
+    :value="selectedSeverities"
+    :valid-values="$options.VALID_IDS"
+    @input="updateSelectedFromQS"
   >
-    <template #view>
-      {{ toggleText }}
-    </template>
-    <template #suggestions>
-      <gl-filtered-search-suggestion
-        v-for="severity in $options.items"
-        :key="severity.value"
-        :value="severity.value"
-      >
-        <div class="gl-display-flex gl-align-items-center">
-          <gl-icon
-            name="check"
-            class="gl-mr-3 gl-flex-shrink-0 gl-text-gray-700"
-            :class="{ 'gl-visibility-hidden': !isSeveritySelected(severity.value) }"
-            :data-testid="`severity-icon-${severity.value}`"
-          />
-          {{ severity.text }}
-        </div>
-      </gl-filtered-search-suggestion>
-    </template>
-  </gl-filtered-search-token>
+    <gl-filtered-search-token
+      :config="config"
+      v-bind="{ ...$props, ...$attrs }"
+      :multi-select-values="selectedSeverities"
+      :value="tokenValue"
+      v-on="$listeners"
+      @select="toggleSelected"
+      @destroy="resetSelected"
+      @complete="emitFiltersChanged"
+    >
+      <template #view>
+        {{ toggleText }}
+      </template>
+      <template #suggestions>
+        <gl-filtered-search-suggestion
+          v-for="severity in $options.items"
+          :key="severity.value"
+          :value="severity.value"
+        >
+          <div class="gl-display-flex gl-align-items-center">
+            <gl-icon
+              name="check"
+              class="gl-mr-3 gl-flex-shrink-0 gl-text-gray-700"
+              :class="{ 'gl-visibility-hidden': !isSeveritySelected(severity.value) }"
+              :data-testid="`severity-icon-${severity.value}`"
+            />
+            {{ severity.text }}
+          </div>
+        </gl-filtered-search-suggestion>
+      </template>
+    </gl-filtered-search-token>
+  </querystring-sync>
 </template>
diff --git a/ee/app/assets/javascripts/security_dashboard/components/shared/filtered_search/vulnerability_report_filtered_search.vue b/ee/app/assets/javascripts/security_dashboard/components/shared/filtered_search/vulnerability_report_filtered_search.vue
index 190ce6a8c836f17f70bf1657c6ca28158ac21cf1..d0121a5db724d3353623c7e66efe84cf432c9f59 100644
--- a/ee/app/assets/javascripts/security_dashboard/components/shared/filtered_search/vulnerability_report_filtered_search.vue
+++ b/ee/app/assets/javascripts/security_dashboard/components/shared/filtered_search/vulnerability_report_filtered_search.vue
@@ -10,16 +10,28 @@ export default {
     GlFilteredSearch,
   },
   data() {
-    return {
-      value: [
-        {
-          type: 'state',
-          value: {
-            data: StatusToken.DEFAULT_VALUES,
-            operator: OPERATOR_OR,
-          },
+    const value = [
+      {
+        type: 'state',
+        value: {
+          data: StatusToken.DEFAULT_VALUES,
+          operator: OPERATOR_OR,
         },
-      ],
+      },
+    ];
+
+    if (this.$route.query.severity) {
+      value.push({
+        type: 'severity',
+        value: {
+          data: this.$route.query.severity.split(','),
+          operator: OPERATOR_OR,
+        },
+      });
+    }
+
+    return {
+      value,
     };
   },
   computed: {
diff --git a/ee/spec/frontend/security_dashboard/components/shared/filtered_search/tokens/severity_token_spec.js b/ee/spec/frontend/security_dashboard/components/shared/filtered_search/tokens/severity_token_spec.js
index 88fa4a05f77c380008e8156b25ee9e7aeb9d3b05..bd0e4e3e698f955a8e7b4744f52a8448cc2f67a1 100644
--- a/ee/spec/frontend/security_dashboard/components/shared/filtered_search/tokens/severity_token_spec.js
+++ b/ee/spec/frontend/security_dashboard/components/shared/filtered_search/tokens/severity_token_spec.js
@@ -1,12 +1,18 @@
 import { GlFilteredSearchToken } from '@gitlab/ui';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
+import VueRouter from 'vue-router';
 import SeverityToken from 'ee/security_dashboard/components/shared/filtered_search/tokens/severity_token.vue';
+import QuerystringSync from 'ee/security_dashboard/components/shared/filters/querystring_sync.vue';
+import eventHub from 'ee/security_dashboard/components/shared/filtered_search/event_hub';
 import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
 import { stubComponent } from 'helpers/stub_component';
 import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
 
+Vue.use(VueRouter);
+
 describe('Severity Token component', () => {
   let wrapper;
+  let router;
 
   const mockConfig = {
     multiSelect: true,
@@ -20,7 +26,10 @@ describe('Severity Token component', () => {
     stubs,
     mountFn = shallowMountExtended,
   } = {}) => {
+    router = new VueRouter({ mode: 'history' });
+
     wrapper = mountFn(SeverityToken, {
+      router,
       propsData: {
         config: mockConfig,
         value,
@@ -36,8 +45,10 @@ describe('Severity Token component', () => {
     });
   };
 
+  const findQuerystringSync = () => wrapper.findComponent(QuerystringSync);
   const findFilteredSearchToken = () => wrapper.findComponent(GlFilteredSearchToken);
   const findCheckedIcon = (value) => wrapper.findByTestId(`severity-icon-${value}`);
+  const isOptionChecked = (v) => !findCheckedIcon(v).classes('gl-visibility-hidden');
 
   const clickDropdownItem = async (...ids) => {
     await Promise.all(
@@ -47,11 +58,14 @@ describe('Severity Token component', () => {
       }),
     );
 
+    findFilteredSearchToken().vm.$emit('complete');
     await nextTick();
   };
 
   const allOptionsExcept = (value) => {
-    return SeverityToken.items.map((i) => i.value).filter((i) => i !== value);
+    const exempt = Array.isArray(value) ? value : [value];
+
+    return SeverityToken.items.map((i) => i.value).filter((i) => !exempt.includes(i));
   };
 
   describe('default view', () => {
@@ -98,8 +112,6 @@ describe('Severity Token component', () => {
     });
 
     it('toggles the item selection when clicked on', async () => {
-      const isOptionChecked = (v) => !findCheckedIcon(v).classes('gl-visibility-hidden');
-
       await clickDropdownItem('CRITICAL', 'HIGH');
 
       expect(isOptionChecked('ALL')).toBe(false);
@@ -129,6 +141,18 @@ describe('Severity Token component', () => {
         expect(isOptionChecked(value)).toBe(false);
       });
     });
+
+    it('emits filters-changed event when a filter is selected', async () => {
+      const spy = jest.fn();
+      eventHub.$on('filters-changed', spy);
+
+      // Select 2 states
+      await clickDropdownItem('MEDIUM', 'HIGH');
+
+      expect(spy).toHaveBeenCalledWith({
+        severity: ['MEDIUM', 'HIGH'],
+      });
+    });
   });
 
   describe('toggle text', () => {
@@ -158,4 +182,41 @@ describe('Severity Token component', () => {
       expect(findSlotView().text()).toBe('Low');
     });
   });
+
+  describe('QuerystringSync component', () => {
+    beforeEach(() => {
+      createWrapper({});
+    });
+
+    it('has expected props', () => {
+      expect(findQuerystringSync().props()).toMatchObject({
+        querystringKey: 'severity',
+        value: ['ALL'],
+        validValues: SeverityToken.VALID_IDS,
+      });
+    });
+
+    it('receives ALL_STATUS_VALUE when All Statuses option is clicked', async () => {
+      await clickDropdownItem('ALL');
+
+      expect(findQuerystringSync().props('value')).toEqual(['ALL']);
+    });
+
+    it.each`
+      emitted                   | expected
+      ${['CRITICAL', 'MEDIUM']} | ${['CRITICAL', 'MEDIUM']}
+      ${['ALL']}                | ${['ALL']}
+    `('restores selected items from the query string - $emitted', async ({ emitted, expected }) => {
+      findQuerystringSync().vm.$emit('input', emitted);
+      await nextTick();
+
+      expected.forEach((item) => {
+        expect(isOptionChecked(item)).toBe(true);
+      });
+
+      allOptionsExcept(expected).forEach((item) => {
+        expect(isOptionChecked(item)).toBe(false);
+      });
+    });
+  });
 });
diff --git a/ee/spec/frontend/security_dashboard/components/shared/filtered_search/vulnerability_report_filtered_search_spec.js b/ee/spec/frontend/security_dashboard/components/shared/filtered_search/vulnerability_report_filtered_search_spec.js
index 2d725ad9a0fb303a795ba734edd502bd70c3bbd5..0fe50508f3a9b93fe7dc3abfb4d6c4dc0ee8f863 100644
--- a/ee/spec/frontend/security_dashboard/components/shared/filtered_search/vulnerability_report_filtered_search_spec.js
+++ b/ee/spec/frontend/security_dashboard/components/shared/filtered_search/vulnerability_report_filtered_search_spec.js
@@ -1,3 +1,5 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
 import { GlFilteredSearch } from '@gitlab/ui';
 import { mountExtended } from 'helpers/vue_test_utils_helper';
 import FilteredSearch from 'ee/security_dashboard/components/shared/filtered_search/vulnerability_report_filtered_search.vue';
@@ -6,61 +8,98 @@ import SeverityToken from 'ee/security_dashboard/components/shared/filtered_sear
 import eventHub from 'ee/security_dashboard/components/shared/filtered_search/event_hub';
 import { OPERATORS_OR } from '~/vue_shared/components/filtered_search_bar/constants';
 
+Vue.use(VueRouter);
+
 describe('Vulnerability Report Filtered Search component', () => {
   let wrapper;
+  let router;
 
   const findFilteredSearchComponent = () => wrapper.findComponent(GlFilteredSearch);
 
-  const createWrapper = () => {
+  const createWrapper = ({ query } = {}) => {
+    router = new VueRouter({ mode: 'history' });
+
+    if (query) {
+      router.push({ query });
+    }
+
     wrapper = mountExtended(FilteredSearch, {
+      router,
       stubs: {
         QuerystringSync: true,
       },
     });
   };
 
-  beforeEach(() => {
-    createWrapper();
-  });
+  describe('with empty query parameters', () => {
+    beforeEach(() => {
+      createWrapper();
+    });
 
-  it('should mount the component with the correct config', () => {
-    const filteredSearch = findFilteredSearchComponent();
+    it('should mount the component with the correct config', () => {
+      const filteredSearch = findFilteredSearchComponent();
 
-    expect(filteredSearch.props('placeholder')).toEqual('Search or filter vulnerabilities...');
+      expect(filteredSearch.props('placeholder')).toEqual('Search or filter vulnerabilities...');
 
-    expect(filteredSearch.props('value')).toEqual([
-      {
-        type: 'state',
-        value: {
-          data: StatusToken.DEFAULT_VALUES,
-          operator: '||',
+      expect(filteredSearch.props('value')).toEqual([
+        {
+          type: 'state',
+          value: {
+            data: StatusToken.DEFAULT_VALUES,
+            operator: '||',
+          },
         },
-      },
-    ]);
+      ]);
 
-    expect(filteredSearch.props('availableTokens')).toEqual([
-      {
-        type: 'state',
-        title: 'Status',
-        multiSelect: true,
-        unique: true,
-        token: StatusToken,
-        operators: OPERATORS_OR,
-      },
-      {
-        type: 'severity',
-        title: 'Severity',
-        multiSelect: true,
-        unique: true,
-        token: SeverityToken,
-        operators: OPERATORS_OR,
-      },
-    ]);
+      expect(filteredSearch.props('availableTokens')).toEqual([
+        {
+          type: 'state',
+          title: 'Status',
+          multiSelect: true,
+          unique: true,
+          token: StatusToken,
+          operators: OPERATORS_OR,
+        },
+        {
+          type: 'severity',
+          title: 'Severity',
+          multiSelect: true,
+          unique: true,
+          token: SeverityToken,
+          operators: OPERATORS_OR,
+        },
+      ]);
+    });
+
+    it('should propagate when event hub emits a `filters-changed` event', () => {
+      const eventObj = { state: ['DISMISSED'] };
+      eventHub.$emit('filters-changed', eventObj);
+      expect(wrapper.emitted('filters-changed')).toEqual([[eventObj]]);
+    });
   });
 
-  it('should propagate when event hub emits a `filters-changed` event', () => {
-    const eventObj = { state: ['DISMISSED'] };
-    eventHub.$emit('filters-changed', eventObj);
-    expect(wrapper.emitted('filters-changed')).toEqual([[eventObj]]);
+  describe('with non-empty query parameters', () => {
+    beforeEach(() => {
+      createWrapper({ query: { severity: 'MEDIUM,LOW' } });
+    });
+
+    it('should pass route parameters to the severity token', () => {
+      expect(findFilteredSearchComponent().props('value')).toEqual([
+        {
+          type: 'state',
+          value: {
+            data: StatusToken.DEFAULT_VALUES,
+            operator: '||',
+          },
+        },
+        {
+          type: 'severity',
+          value: {
+            data: ['MEDIUM', 'LOW'],
+            operator: '||',
+          },
+        },
+      ]);
+    });
   });
 });