diff --git a/ee/app/assets/javascripts/on_demand_scans_form/graphql/provider.js b/ee/app/assets/javascripts/on_demand_scans_form/graphql/provider.js
deleted file mode 100644
index ef96b443da8d33b03b587827a13b5d9c53a40fd3..0000000000000000000000000000000000000000
--- a/ee/app/assets/javascripts/on_demand_scans_form/graphql/provider.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
-
-Vue.use(VueApollo);
-
-export default new VueApollo({
-  defaultClient: createDefaultClient(),
-});
diff --git a/ee/app/assets/javascripts/on_demand_scans_form/index.js b/ee/app/assets/javascripts/on_demand_scans_form/index.js
index 25f1a2045df0aecb630acd439d7ad7f8a493d754..77f14dd2a870e8b95bd7eec11b1c9c6749e69307 100644
--- a/ee/app/assets/javascripts/on_demand_scans_form/index.js
+++ b/ee/app/assets/javascripts/on_demand_scans_form/index.js
@@ -1,6 +1,6 @@
 import Vue from 'vue';
+import apolloProvider from 'ee/vue_shared/security_configuration/graphql/provider';
 import OnDemandScansForm from './components/on_demand_scans_form.vue';
-import apolloProvider from './graphql/provider';
 
 export default () => {
   const el = document.querySelector('#js-on-demand-scans-form');
diff --git a/ee/app/assets/javascripts/security_configuration/dast/index.js b/ee/app/assets/javascripts/security_configuration/dast/index.js
index 35af286c05c6091d2d6dc0f5e333d35438c7d9d9..5486849698200ca8b5e30876cae05019670f3dfb 100644
--- a/ee/app/assets/javascripts/security_configuration/dast/index.js
+++ b/ee/app/assets/javascripts/security_configuration/dast/index.js
@@ -1,6 +1,5 @@
 import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
+import apolloProvider from 'ee/vue_shared/security_configuration/graphql/provider';
 import DastConfigurationApp from './components/app.vue';
 
 export default function init() {
@@ -10,12 +9,6 @@ export default function init() {
     return undefined;
   }
 
-  Vue.use(VueApollo);
-
-  const apolloProvider = new VueApollo({
-    defaultClient: createDefaultClient(),
-  });
-
   const {
     securityConfigurationPath,
     fullPath,
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/components/base_dast_profile_form.vue b/ee/app/assets/javascripts/security_configuration/dast_profiles/components/base_dast_profile_form.vue
index d93587e40bcd8aafdb8ce5f64482c5f38f7845c1..018ce8e68b6e6d5bee6cd7d8cb2d097d2068f72d 100644
--- a/ee/app/assets/javascripts/security_configuration/dast_profiles/components/base_dast_profile_form.vue
+++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/components/base_dast_profile_form.vue
@@ -1,6 +1,8 @@
 <script>
 import { GlAlert, GlButton, GlForm, GlModal } from '@gitlab/ui';
 import * as Sentry from '@sentry/browser';
+import { s__ } from '~/locale';
+import dastProfileConfiguratorMixin from 'ee/security_configuration/dast_profiles/dast_profiles_configurator_mixin';
 
 export default {
   components: {
@@ -9,6 +11,22 @@ export default {
     GlForm,
     GlModal,
   },
+  i18n: {
+    discardChangesHeader: s__('OnDemandScans|You have unsaved changes'),
+    discardChangesText: s__(
+      'OnDemandScans|Do you want to discard the changes or keep editing this profile? Unsaved changes will be lost.',
+    ),
+  },
+  modal: {
+    actionPrimary: {
+      text: s__('OnDemandScans|Discard changes'),
+      attributes: { variant: 'danger', 'data-testid': 'form-touched-warning' },
+    },
+    actionCancel: {
+      text: s__('OnDemandScans|Keep editing'),
+    },
+  },
+  mixins: [dastProfileConfiguratorMixin()],
   props: {
     profile: {
       type: Object,
@@ -47,18 +65,20 @@ export default {
       required: false,
       default: false,
     },
-    modalProps: {
-      type: Object,
-      required: true,
-    },
   },
   data() {
     return {
       isLoading: false,
       showAlert: false,
       errors: [],
+      sharedData: {},
     };
   },
+  watch: {
+    formTouched(isTouched) {
+      this.setFormTouched({ isTouched });
+    },
+  },
   methods: {
     onSubmit() {
       this.$emit('submit');
@@ -100,16 +120,20 @@ export default {
           this.isLoading = false;
         });
     },
-    onCancelClicked() {
+    async onCancelClicked() {
       if (!this.formTouched) {
-        this.discard();
+        this.$emit('cancel');
       } else {
-        this.$refs[this.$options.modalId].show();
+        await this.toggleModal({ showModal: true });
       }
     },
-    discard() {
+    async discard() {
+      await this.discardChanges();
       this.$emit('cancel');
     },
+    async keepEditing() {
+      await this.toggleModal({ showModal: false });
+    },
     showErrors(errors = []) {
       this.errors = errors;
       this.showAlert = true;
@@ -174,12 +198,19 @@ export default {
 
     <gl-modal
       :ref="$options.modalId"
+      size="sm"
       :modal-id="$options.modalId"
-      v-bind="modalProps"
+      :visible="sharedData.showDiscardChangesModal"
+      :title="$options.i18n.discardChangesHeader"
+      :action-primary="$options.modal.actionPrimary"
+      :action-cancel="$options.modal.actionCancel"
       ok-variant="danger"
-      body-class="gl-display-none"
       data-testid="dast-profile-form-cancel-modal"
-      @ok="discard"
-    />
+      @change="keepEditing"
+      @canceled="keepEditing"
+      @primary="discard"
+    >
+      {{ $options.i18n.discardChangesText }}
+    </gl-modal>
   </gl-form>
 </template>
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator.vue b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator.vue
index 3bac20f105eaea2a2eb138a59ccce6128dcfab25..eb1e9fde25d5a141f722ffd32cd3c112a863e456 100644
--- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator.vue
+++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator.vue
@@ -8,6 +8,7 @@ import { TYPE_SCANNER_PROFILE, TYPE_SITE_PROFILE } from '~/graphql_shared/consta
 import DastProfilesSidebar from 'ee/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue';
 import ScannerProfileSelector from 'ee/security_configuration/dast_profiles/dast_profile_selector/scanner_profile_selector.vue';
 import SiteProfileSelector from 'ee/security_configuration/dast_profiles/dast_profile_selector/site_profile_selector.vue';
+import dastProfileConfiguratorMixin from 'ee/security_configuration/dast_profiles/dast_profiles_configurator_mixin';
 import {
   DAST_CONFIGURATION_HELP_PATH,
   SCANNER_TYPE,
@@ -83,6 +84,7 @@ export default {
       SITE_PROFILES_QUERY,
     ),
   },
+  mixins: [dastProfileConfiguratorMixin()],
   props: {
     configurationHeader: {
       type: String,
@@ -124,11 +126,9 @@ export default {
     return {
       scannerProfiles: [],
       siteProfiles: [],
-      sidebarViewMode: SIDEBAR_VIEW_MODE.READING_MODE,
       errorType: null,
       isSideDrawerOpen: false,
-      profileType: '',
-      activeProfile: {},
+      activeProfile: undefined,
       selectedScannerProfileId: this.savedProfiles?.dastScannerProfile.id || null,
       selectedSiteProfileId: this.savedProfiles?.dastSiteProfile.id || null,
     };
@@ -196,14 +196,31 @@ export default {
     findSavedProfileId(profiles, name) {
       return profiles.find(({ profileName }) => name === profileName)?.id || null;
     },
-    enableEditingMode(type) {
-      this.selectActiveProfile(type);
-      this.openProfileDrawer({ profileType: type, mode: SIDEBAR_VIEW_MODE.EDITING_MODE });
+    enableEditingMode({ profileType }) {
+      this.resetActiveProfile();
+
+      this.$nextTick(() => {
+        this.selectActiveProfile(profileType);
+        this.openProfileDrawer({ profileType, mode: SIDEBAR_VIEW_MODE.EDITING_MODE });
+      });
+    },
+    reopenProfileDrawer() {
+      this.isSideDrawerOpen = false;
+      this.$nextTick(() => {
+        this.isSideDrawerOpen = true;
+      });
     },
-    openProfileDrawer({ profileType, mode }) {
+    async openProfileDrawer({ profileType, mode }) {
+      if (this.sharedData.formTouched) {
+        this.toggleModal({ showModal: true });
+        await this.setCachedPayload({ profileType, mode });
+
+        return;
+      }
+
+      await this.goFirstStep({ profileType, mode });
+
       this.isSideDrawerOpen = false;
-      this.sidebarViewMode = mode;
-      this.profileType = profileType;
       this.$nextTick(() => {
         this.isSideDrawerOpen = true;
       });
@@ -211,14 +228,15 @@ export default {
     closeProfileDrawer() {
       this.isSideDrawerOpen = false;
       this.activeProfile = {};
-      this.sidebarViewMode = SIDEBAR_VIEW_MODE.READING_MODE;
     },
     selectActiveProfile(type) {
       this.activeProfile =
         type === SCANNER_TYPE ? this.selectedScannerProfile : this.selectedSiteProfile;
     },
-    selectProfile(payload) {
+    async selectProfile(payload) {
       this.updateProfileFromSelector(payload);
+      await this.goBack();
+
       this.closeProfileDrawer();
     },
     isNewProfile(id) {
@@ -251,6 +269,9 @@ export default {
       const type = `${profileType}Profiles`;
       this.$apollo.queries[type].refetch();
     },
+    resetActiveProfile() {
+      this.activeProfile = undefined;
+    },
   },
 };
 </script>
@@ -282,7 +303,11 @@ export default {
               mode: $options.SIDEBAR_VIEW_MODE.READING_MODE,
             })
           "
-          @edit="enableEditingMode($options.SCANNER_TYPE)"
+          @edit="
+            enableEditingMode({
+              profileType: $options.SCANNER_TYPE,
+            })
+          "
         />
 
         <site-profile-selector
@@ -295,7 +320,11 @@ export default {
               mode: $options.SIDEBAR_VIEW_MODE.READING_MODE,
             })
           "
-          @edit="enableEditingMode($options.SITE_TYPE)"
+          @edit="
+            enableEditingMode({
+              profileType: $options.SITE_TYPE,
+            })
+          "
         />
       </template>
     </section-layout>
@@ -305,13 +334,11 @@ export default {
       :profile-id-in-use="profileIdInUse"
       :active-profile="activeProfile"
       :library-link="libraryLink"
-      :profile-type="profileType"
       :is-open="isSideDrawerOpen"
       :is-loading="isLoadingProfiles"
       :selected-profile-id="selectedProfileId"
-      :sidebar-view-mode="sidebarViewMode"
       @close-drawer="closeProfileDrawer"
-      @reopen-drawer="openProfileDrawer"
+      @reopen-drawer="reopenProfileDrawer"
       @select-profile="selectProfile"
       @profile-submitted="onScannerProfileCreated"
     />
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator_mixin.js b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator_mixin.js
new file mode 100644
index 0000000000000000000000000000000000000000..592e58e42caba8d5e674e884ec9eb5f698dc1a22
--- /dev/null
+++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_configurator_mixin.js
@@ -0,0 +1,99 @@
+import { SCANNER_TYPE, SIDEBAR_VIEW_MODE } from 'ee/on_demand_scans/constants';
+import getSharedStateQuery from 'ee/vue_shared/security_configuration/graphql/client/queries/shared_sidebar_state.query.graphql';
+import goFirstStepMutation from 'ee/vue_shared/security_configuration/graphql/client/mutations/go_first_history_step.mutation.graphql';
+import goForwardMutation from 'ee/vue_shared/security_configuration/graphql/client/mutations/go_forward_history.mutation.graphql';
+import discardMutationsMutation from 'ee/vue_shared/security_configuration/graphql/client/mutations/discard_changes.mutation.graphql';
+import toggleModalMutation from 'ee/vue_shared/security_configuration/graphql/client/mutations/toggle_modal.mutation.graphql';
+import resetHistoryMutation from 'ee/vue_shared/security_configuration/graphql/client/mutations/reset_history.mutation.graphql';
+import setFormTouchedMutation from 'ee/vue_shared/security_configuration/graphql/client/mutations/set_form_touched.mutation.graphql';
+import setResetAndClose from 'ee/vue_shared/security_configuration/graphql/client/mutations/set_reset_and_close.mutation.graphql';
+import setCachedPayloadMutation from 'ee/vue_shared/security_configuration/graphql/client/mutations/set_cached_payload.mutation.graphql';
+import goBackMutation from 'ee/vue_shared/security_configuration/graphql/client/mutations/go_back_history.mutation.graphql';
+
+export default () => ({
+  apollo: {
+    sharedData: {
+      query: getSharedStateQuery,
+    },
+  },
+  data() {
+    return {
+      sharedData: {},
+    };
+  },
+  computed: {
+    hasCachedPayload() {
+      return Boolean(this.sharedData.cachedPayload?.profileType);
+    },
+    cachedPayload() {
+      return this.sharedData.cachedPayload;
+    },
+    lastHistoryIndex() {
+      return (this.sharedData.history?.length || 0) > 0 ? this.sharedData.history.length - 1 : 0;
+    },
+    profileType() {
+      return this.sharedData.history?.[this.lastHistoryIndex]?.profileType || SCANNER_TYPE;
+    },
+    sidebarViewMode() {
+      return (
+        this.sharedData.history?.[this.lastHistoryIndex]?.mode || SIDEBAR_VIEW_MODE.READING_MODE
+      );
+    },
+    eventName() {
+      return (this.sharedData.history?.length || 0) > 0 ? 'reopen-drawer' : 'close-drawer';
+    },
+  },
+  methods: {
+    goFirstStep({ profileType, mode }) {
+      return this.$apollo.mutate({
+        mutation: goFirstStepMutation,
+        variables: { profileType, mode },
+      });
+    },
+    goForward({ profileType, mode }) {
+      return this.$apollo.mutate({
+        mutation: goForwardMutation,
+        variables: { profileType, mode },
+      });
+    },
+    goBack() {
+      return this.$apollo.mutate({
+        mutation: goBackMutation,
+      });
+    },
+    toggleModal({ showModal }) {
+      return this.$apollo.mutate({
+        mutation: toggleModalMutation,
+        variables: { showDiscardChangesModal: showModal },
+      });
+    },
+    discardChanges() {
+      return this.$apollo.mutate({
+        mutation: discardMutationsMutation,
+      });
+    },
+    setFormTouched({ isTouched }) {
+      return this.$apollo.mutate({
+        mutation: setFormTouchedMutation,
+        variables: { formTouched: isTouched },
+      });
+    },
+    resetHistory() {
+      return this.$apollo.mutate({
+        mutation: resetHistoryMutation,
+      });
+    },
+    setCachedPayload({ profileType, mode } = { profileType: '', mode: '' }) {
+      return this.$apollo.mutate({
+        mutation: setCachedPayloadMutation,
+        variables: { cachedPayload: { profileType, mode } },
+      });
+    },
+    setResetAndClose({ resetAndClose }) {
+      return this.$apollo.mutate({
+        mutation: setResetAndClose,
+        variables: { resetAndClose },
+      });
+    },
+  },
+});
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue
index fb6f52439bb867de6f592297844e62a1483a775b..57e389de5473a7f25880173b4b863747475ae75b 100644
--- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue
+++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue
@@ -2,35 +2,15 @@
 import { isEmpty } from 'lodash';
 import { GlDrawer, GlLink } from '@gitlab/ui';
 import { s__, sprintf } from '~/locale';
-import { SCANNER_TYPE, SIDEBAR_VIEW_MODE } from 'ee/on_demand_scans/constants';
-import { REFERRAL } from 'ee/security_configuration/dast_profiles/dast_scanner_profiles/constants';
+import { SIDEBAR_VIEW_MODE } from 'ee/on_demand_scans/constants';
 import DastProfilesLoader from 'ee/security_configuration/dast_profiles/components/dast_profiles_loader.vue';
 import { getContentWrapperHeight } from 'ee/security_orchestration/utils';
+import dastProfileConfiguratorMixin from 'ee/security_configuration/dast_profiles/dast_profiles_configurator_mixin';
 import DastProfilesSidebarHeader from './dast_profiles_sidebar_header.vue';
 import DastProfilesSidebarEmptyState from './dast_profiles_sidebar_empty_state.vue';
 import DastProfilesSidebarForm from './dast_profiles_sidebar_form.vue';
 import DastProfilesSidebarList from './dast_profiles_sidebar_list.vue';
 
-/**
- *                   Referral
- *                  /        \
- *            Parent          Self
- *           /      \        /    \
- *        New      Edit     New     Edit
- *      /   \      /  \     / \     / \
- *     C     R    C    C   C   R   R   R
- *
- * New profile or edit existing can be called both from component and parent
- * When form is opened it can be closed either by submit or cancel
- * This tree represent behaviour of a drawer.
- * Bottom level left subtree is after submit right subtree is after cancel
- *
- * For example Opened from parent -> new profile -> close after submit or reopen after cancel
- *
- * C-close
- * R-reopen
- */
-
 export default {
   SIDEBAR_VIEW_MODE,
   i18n: {
@@ -45,6 +25,7 @@ export default {
     DastProfilesSidebarForm,
     DastProfilesSidebarList,
   },
+  mixins: [dastProfileConfiguratorMixin()],
   props: {
     isOpen: {
       type: Boolean,
@@ -66,15 +47,6 @@ export default {
       required: false,
       default: null,
     },
-    /**
-     * String type in case
-     * there will be more types
-     */
-    profileType: {
-      type: String,
-      required: false,
-      default: SCANNER_TYPE,
-    },
     isLoading: {
       type: Boolean,
       required: false,
@@ -92,11 +64,6 @@ export default {
       required: false,
       default: () => ({}),
     },
-    sidebarViewMode: {
-      type: String,
-      required: false,
-      default: SIDEBAR_VIEW_MODE.READING_MODE,
-    },
     libraryLink: {
       type: String,
       required: false,
@@ -106,7 +73,7 @@ export default {
   data() {
     return {
       profileForEditing: {},
-      referral: REFERRAL.SELF,
+      sharedData: {},
     };
   },
   computed: {
@@ -144,53 +111,73 @@ export default {
   watch: {
     activeProfile(newVal) {
       if (!isEmpty(newVal)) {
-        this.referral = REFERRAL.PARENT;
-        this.enableEditingMode({
-          profile: this.activeProfile,
-          mode: SIDEBAR_VIEW_MODE.EDITING_MODE,
-        });
+        this.profileForEditing = this.activeProfile;
       }
     },
   },
   methods: {
-    resetAndEmitCloseEvent() {
+    async resetAndEmitCloseEvent() {
+      if (this.sharedData.formTouched) {
+        await this.toggleModal({ showModal: true });
+        await this.setResetAndClose({ resetAndClose: true });
+
+        return;
+      }
+
       this.resetEditingMode();
+      await this.resetHistory();
       this.$emit('close-drawer');
     },
     resetEditingMode() {
       this.profileForEditing = {};
-      this.referral = REFERRAL.SELF;
     },
     enableEditingMode({ profile = {}, mode }) {
       this.profileForEditing = profile;
+
+      this.goForward({ profileType: this.profileType, mode });
       this.$emit('reopen-drawer', { profileType: this.profileType, mode });
     },
     /**
      * reopen even for closing editing layer
      * and opening drawer with profiles list
      */
-    cancelEditingMode() {
-      const event = this.referral === REFERRAL.PARENT ? 'close-drawer' : 'reopen-drawer';
+    async cancelEditingMode() {
+      if (this.sharedData.resetAndClose) {
+        await this.resetAndEmitCloseEvent();
+        this.setResetAndClose({ resetAndClose: false });
+      }
 
-      this.$emit(event, { profileType: this.profileType, mode: SIDEBAR_VIEW_MODE.READING_MODE });
-      this.resetEditingMode();
+      await this.goBack();
+
+      if (this.hasCachedPayload) {
+        await this.goFirstStep(this.cachedPayload);
+      }
+
+      this.$emit(this.eventName, { profileType: this.profileType, mode: this.sidebarViewMode });
+      await this.setCachedPayload(undefined);
     },
-    profileCreated(profile) {
+    async profileCreated(profile) {
       this.$emit('profile-submitted', { profile, profileType: this.profileType });
-      this.$emit('close-drawer', {
+
+      await this.resetHistory();
+      this.$emit(this.eventName, {
         profileType: this.profileType,
         mode: SIDEBAR_VIEW_MODE.READING_MODE,
       });
+
+      await this.discardChanges();
       this.resetEditingMode();
     },
-    profileEdited(profile) {
+    async profileEdited(profile) {
       this.$emit('profile-submitted', { profile, profileType: this.profileType });
 
-      const secondaryEvent = this.referral === REFERRAL.PARENT ? 'close-drawer' : 'reopen-drawer';
-      this.$emit(secondaryEvent, {
+      await this.goBack();
+      this.$emit(this.eventName, {
         profileType: this.profileType,
         mode: SIDEBAR_VIEW_MODE.READING_MODE,
       });
+
+      await this.discardChanges();
       this.resetEditingMode();
     },
   },
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/components/dast_scanner_profile_form.vue b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/components/dast_scanner_profile_form.vue
index 5995c3a7514e3551c69079935585f98190f0b542..2ede07bcb81ab0cca51c07a846e41112d9eafdfc 100644
--- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/components/dast_scanner_profile_form.vue
+++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/components/dast_scanner_profile_form.vue
@@ -10,7 +10,7 @@ import {
 } from '@gitlab/ui';
 import { initFormField } from 'ee/security_configuration/utils';
 import { serializeFormObject } from '~/lib/utils/forms';
-import { __, s__ } from '~/locale';
+import { s__ } from '~/locale';
 import BaseDastProfileForm from '../../components/base_dast_profile_form.vue';
 import dastProfileFormMixin from '../../dast_profile_form_mixin';
 import { SCAN_TYPE, SCAN_TYPE_OPTIONS } from '../constants';
@@ -94,13 +94,6 @@ export default {
         errorMessage: isEdit
           ? s__('DastProfiles|Could not update the scanner profile. Please try again.')
           : s__('DastProfiles|Could not create the scanner profile. Please try again.'),
-        modal: {
-          title: isEdit
-            ? s__('DastProfiles|Do you want to discard your changes?')
-            : s__('DastProfiles|Do you want to discard this scanner profile?'),
-          okTitle: __('Discard'),
-          cancelTitle: __('Cancel'),
-        },
         tooltips: {
           spiderTimeout: s__(
             'DastProfiles|The maximum number of minutes allowed for the spider to traverse the site.',
@@ -142,11 +135,6 @@ export default {
     :is-policy-profile="isPolicyProfile"
     :block-submit="!form.state"
     :show-header="!stacked"
-    :modal-props="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ {
-      title: i18n.modal.title,
-      okTitle: i18n.modal.okTitle,
-      cancelTitle: i18n.modal.cancelTitle,
-    } /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
     @submit="form.showValidation = true"
     v-on="$listeners"
   >
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/dast_scanner_profiles_bundle.js b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/dast_scanner_profiles_bundle.js
index 84abf39f5093224ec5c0b8402f0ac78d64c27c9d..bd48200620e873c7bdc55e0bb91ab18cb8e77eed 100644
--- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/dast_scanner_profiles_bundle.js
+++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/dast_scanner_profiles_bundle.js
@@ -1,8 +1,8 @@
 import Vue from 'vue';
 import { returnToPreviousPageFactory } from 'ee/security_configuration/dast_profiles/redirect';
+import apolloProvider from 'ee/vue_shared/security_configuration/graphql/provider';
 import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
 import DastScannerProfileForm from './components/dast_scanner_profile_form.vue';
-import apolloProvider from './graphql/provider';
 
 export default () => {
   const el = document.querySelector('.js-dast-scanner-profile-form');
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/graphql/provider.js b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/graphql/provider.js
deleted file mode 100644
index ef96b443da8d33b03b587827a13b5d9c53a40fd3..0000000000000000000000000000000000000000
--- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_scanner_profiles/graphql/provider.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
-
-Vue.use(VueApollo);
-
-export default new VueApollo({
-  defaultClient: createDefaultClient(),
-});
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/components/dast_site_profile_form.vue b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/components/dast_site_profile_form.vue
index f65692b252e888d6435e2b27d48e3987197aef4d..fd556a7f84c80e3f8e5be78a3b061e91ba978655 100644
--- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/components/dast_site_profile_form.vue
+++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/components/dast_site_profile_form.vue
@@ -106,13 +106,6 @@ export default {
         errorMessage: isEdit
           ? s__('DastProfiles|Could not update the site profile. Please try again.')
           : s__('DastProfiles|Could not create the site profile. Please try again.'),
-        modal: {
-          title: isEdit
-            ? s__('DastProfiles|Do you want to discard your changes?')
-            : s__('DastProfiles|Do you want to discard this site profile?'),
-          okTitle: __('Discard'),
-          cancelTitle: __('Cancel'),
-        },
         excludedUrls: {
           label: this.isTargetAPI
             ? s__('DastProfiles|Excluded paths (optional)')
@@ -233,11 +226,6 @@ export default {
     :is-policy-profile="isPolicyProfile"
     :block-submit="isSubmitBlocked"
     :show-header="!stacked"
-    :modal-props="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ {
-      title: i18n.modal.title,
-      okTitle: i18n.modal.okTitle,
-      cancelTitle: i18n.modal.cancelTitle,
-    } /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
     @submit="form.showValidation = true"
     v-on="$listeners"
   >
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/dast_site_profiles_bundle.js b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/dast_site_profiles_bundle.js
index cf32c7fd1ed64460f3c2587ea29d3ec2e98c281b..71bea316f560253071b3253abaf5e8a8751c96f4 100644
--- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/dast_site_profiles_bundle.js
+++ b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/dast_site_profiles_bundle.js
@@ -1,8 +1,8 @@
 import Vue from 'vue';
 import { returnToPreviousPageFactory } from 'ee/security_configuration/dast_profiles/redirect';
+import apolloProvider from 'ee/vue_shared/security_configuration/graphql/provider';
 import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
 import DastSiteProfileForm from './components/dast_site_profile_form.vue';
-import apolloProvider from './graphql/provider';
 
 export default () => {
   const el = document.querySelector('.js-dast-site-profile-form');
diff --git a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/graphql/provider.js b/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/graphql/provider.js
deleted file mode 100644
index ef96b443da8d33b03b587827a13b5d9c53a40fd3..0000000000000000000000000000000000000000
--- a/ee/app/assets/javascripts/security_configuration/dast_profiles/dast_site_profiles/graphql/provider.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
-
-Vue.use(VueApollo);
-
-export default new VueApollo({
-  defaultClient: createDefaultClient(),
-});
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/discard_changes.mutation.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/discard_changes.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..17891f8a83ed9d502c811e037f6592cfb2847906
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/discard_changes.mutation.graphql
@@ -0,0 +1,3 @@
+mutation discardChanges {
+  discardChanges @client
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/go_back_history.mutation.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/go_back_history.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..ad079622389ddf9b9a0bd9c684d565b7501ad1d8
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/go_back_history.mutation.graphql
@@ -0,0 +1,3 @@
+mutation goBack {
+  goBack @client
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/go_first_history_step.mutation.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/go_first_history_step.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..243e18179d330a4049cf20103fe69aef8e24915e
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/go_first_history_step.mutation.graphql
@@ -0,0 +1,3 @@
+mutation goFirstStep($profileType: String!, $mode: String!) {
+  goFirstStep(profileType: $profileType, mode: $mode) @client
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/go_forward_history.mutation.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/go_forward_history.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..74787a151212a284fe4e20b38194f2fcc9c3a50d
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/go_forward_history.mutation.graphql
@@ -0,0 +1,3 @@
+mutation goForward($profileType: String!, $mode: String!) {
+  goForward(profileType: $profileType, mode: $mode) @client
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/reset_history.mutation.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/reset_history.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..720f568adca272405730678d895a037668e08a91
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/reset_history.mutation.graphql
@@ -0,0 +1,3 @@
+mutation resetHistory {
+  resetHistory @client
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/set_cached_payload.mutation.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/set_cached_payload.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..32a965865fd2ab91c589ce1104161f92069f8854
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/set_cached_payload.mutation.graphql
@@ -0,0 +1,3 @@
+mutation setCachedPayload($cachedPayload: CachedPayloadInput!) {
+  setCachedPayload(cachedPayload: $cachedPayload) @client
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/set_form_touched.mutation.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/set_form_touched.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..3f3e4df9960ec503b809940fa389667f64aa136d
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/set_form_touched.mutation.graphql
@@ -0,0 +1,3 @@
+mutation setFormTouched($formTouched: Boolean!) {
+  setFormTouched(formTouched: $formTouched) @client
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/set_reset_and_close.mutation.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/set_reset_and_close.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..cfb5eea3d9834db0c81982b41773d9a2ec691f60
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/set_reset_and_close.mutation.graphql
@@ -0,0 +1,3 @@
+mutation setResetAndClose($resetAndClose: Boolean!) {
+  setResetAndClose(resetAndClose: $resetAndClose) @client
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/toggle_modal.mutation.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/toggle_modal.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..b3a8a02d5551b5e27a0ed98c308c0e1a81d70245
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/mutations/toggle_modal.mutation.graphql
@@ -0,0 +1,3 @@
+mutation toggleModal($showDiscardChangesModal: Boolean!) {
+  toggleModal(showDiscardChangesModal: $showDiscardChangesModal) @client
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/queries/shared_sidebar_state.query.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/queries/shared_sidebar_state.query.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..7517fa3fe66d8f79cd8090de395c75f4ae07a093
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/client/queries/shared_sidebar_state.query.graphql
@@ -0,0 +1,15 @@
+query sharedData {
+  sharedData @client {
+    showDiscardChangesModal
+    formTouched
+    history {
+      profileType
+      mode
+    }
+    cachedPayload {
+      profileType
+      mode
+    }
+    resetAndClose
+  }
+}
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/provider.js b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/provider.js
new file mode 100644
index 0000000000000000000000000000000000000000..4e8fb96c3ad7e8f7b3a95682e3b82187cc548435
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/provider.js
@@ -0,0 +1,38 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import resolvers from './resolvers/resolvers';
+import typeDefs from './typedefs.graphql';
+
+Vue.use(VueApollo);
+
+export const typePolicies = {
+  Query: {
+    fields: {
+      sharedData: {
+        read(cachedData) {
+          return (
+            cachedData || {
+              showDiscardChangesModal: false,
+              formTouched: false,
+              history: [],
+              cachedPayload: {
+                __typename: 'CachedPayload',
+                profileType: '',
+                mode: '',
+              },
+              resetAndClose: false,
+              __typename: 'SharedData',
+            }
+          );
+        },
+      },
+    },
+  },
+};
+
+const defaultClient = createDefaultClient(resolvers, { cacheConfig: { typePolicies }, typeDefs });
+
+export default new VueApollo({
+  defaultClient,
+});
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/resolvers/resolvers.js b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/resolvers/resolvers.js
new file mode 100644
index 0000000000000000000000000000000000000000..c3d3e37ab30351fdc1e634ff8e1fb2951a682fbd
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/resolvers/resolvers.js
@@ -0,0 +1,79 @@
+import getSharedStateQuery from '../client/queries/shared_sidebar_state.query.graphql';
+
+export default {
+  Mutation: {
+    discardChanges(_, __, { cache }) {
+      cache.updateQuery({ query: getSharedStateQuery }, ({ sharedData }) => ({
+        sharedData: {
+          ...sharedData,
+          showDiscardChangesModal: false,
+          formTouched: false,
+        },
+      }));
+    },
+    goFirstStep(_, { profileType, mode }, { cache }) {
+      cache.updateQuery({ query: getSharedStateQuery }, ({ sharedData }) => ({
+        sharedData: {
+          ...sharedData,
+          history: [{ profileType, mode }],
+        },
+      }));
+    },
+    goForward(_, { profileType, mode }, { cache }) {
+      cache.updateQuery({ query: getSharedStateQuery }, ({ sharedData }) => ({
+        sharedData: {
+          ...sharedData,
+          history: [...sharedData.history, { profileType, mode }],
+        },
+      }));
+    },
+    goBack(_, __, { cache }) {
+      cache.updateQuery({ query: getSharedStateQuery }, ({ sharedData }) => ({
+        sharedData: {
+          ...sharedData,
+          history: sharedData.history.slice(0, -1),
+        },
+      }));
+    },
+    resetHistory(_, __, { cache }) {
+      cache.updateQuery({ query: getSharedStateQuery }, ({ sharedData }) => ({
+        sharedData: {
+          ...sharedData,
+          history: [],
+        },
+      }));
+    },
+    toggleModal(_, { showDiscardChangesModal }, { cache }) {
+      cache.updateQuery({ query: getSharedStateQuery }, ({ sharedData }) => ({
+        sharedData: {
+          ...sharedData,
+          showDiscardChangesModal,
+        },
+      }));
+    },
+    setCachedPayload(_, { cachedPayload = { profileType: '', mode: '' } }, { cache }) {
+      cache.updateQuery({ query: getSharedStateQuery }, ({ sharedData }) => ({
+        sharedData: {
+          ...sharedData,
+          cachedPayload,
+        },
+      }));
+    },
+    setFormTouched(_, { formTouched }, { cache }) {
+      cache.updateQuery({ query: getSharedStateQuery }, ({ sharedData }) => ({
+        sharedData: {
+          ...sharedData,
+          formTouched,
+        },
+      }));
+    },
+    setResetAndClose(_, { resetAndClose }, { cache }) {
+      cache.updateQuery({ query: getSharedStateQuery }, ({ sharedData }) => ({
+        sharedData: {
+          ...sharedData,
+          resetAndClose,
+        },
+      }));
+    },
+  },
+};
diff --git a/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/typedefs.graphql b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/typedefs.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..4004f0c69c24eed6fe1bbd9ea5a24c1e5e2b8337
--- /dev/null
+++ b/ee/app/assets/javascripts/vue_shared/security_configuration/graphql/typedefs.graphql
@@ -0,0 +1,33 @@
+type CachedPayload {
+  profileType: String!
+  mode: String!
+}
+
+input CachedPayloadInput {
+  profileType: String!
+  mode: String!
+}
+
+type SharedData {
+  showDiscardChangesModal: Boolean
+  formTouched: Boolean
+  history: [CachedPayload!]!
+  cachedPayload: CachedPayload!
+  resetAndClose: Boolean
+}
+
+extend type Query {
+  sharedData: SharedData
+}
+
+extend type Mutation {
+  discardChanges: LocalErrors
+  goBack: LocalErrors
+  goFirstStep(profileType: String!, mode: String!): LocalErrors
+  goForward(profileType: String!, mode: String!): LocalErrors
+  resetHistory: LocalErrors
+  setCachedPayload(cachedPayload: CachedPayloadInput): LocalErrors
+  setFormTouched(formTouched: Boolean!): LocalErrors
+  setResetAndClose(resetAndClose: Boolean!): LocalErrors
+  toggleModal(showDiscardChangesModal: Boolean!): LocalErrors
+}
diff --git a/ee/spec/frontend/security_configuration/dast_profiles/components/base_dast_profile_form_spec.js b/ee/spec/frontend/security_configuration/dast_profiles/components/base_dast_profile_form_spec.js
index 605cba0f356a8edda03601fe724baf474f229d93..8436b8621138aa7c8339ed7fec0d30599621c99d 100644
--- a/ee/spec/frontend/security_configuration/dast_profiles/components/base_dast_profile_form_spec.js
+++ b/ee/spec/frontend/security_configuration/dast_profiles/components/base_dast_profile_form_spec.js
@@ -5,6 +5,8 @@ import VueApollo from 'vue-apollo';
 import BaseDastProfileForm from 'ee/security_configuration/dast_profiles/components/base_dast_profile_form.vue';
 import dastSiteProfileCreateMutation from 'ee/security_configuration/dast_profiles/dast_site_profiles/graphql/dast_site_profile_create.mutation.graphql';
 import { dastSiteProfileCreate } from 'ee_jest/security_configuration/dast_profiles/dast_site_profiles/mock_data/apollo_mock';
+import resolvers from 'ee/vue_shared/security_configuration/graphql/resolvers/resolvers';
+import { typePolicies } from 'ee/vue_shared/security_configuration/graphql/provider';
 import createMockApollo from 'helpers/mock_apollo_helper';
 import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
 import waitForPromises from 'helpers/wait_for_promises';
@@ -42,7 +44,11 @@ describe('BaseDastProfileForm', () => {
   const expectSubmitNotLoading = () => expect(findSubmitButton().props('loading')).toBe(false);
 
   const createComponent = (options) => {
-    const apolloProvider = createMockApollo([[dastSiteProfileCreateMutation, requestHandler]]);
+    const apolloProvider = createMockApollo(
+      [[dastSiteProfileCreateMutation, requestHandler]],
+      resolvers,
+      { typePolicies },
+    );
 
     const mountOpts = merge(
       {},
@@ -145,10 +151,6 @@ describe('BaseDastProfileForm', () => {
         },
       });
     });
-
-    it('passes props to the modal', () => {
-      expect(findCancelModal().props()).toEqual(expect.objectContaining(modalProps));
-    });
   });
 
   describe('when submitting the form', () => {
@@ -248,24 +250,35 @@ describe('BaseDastProfileForm', () => {
     });
 
     describe('after changing the form', () => {
-      beforeEach(() => {
+      it('asks the user to confirm the action', async () => {
         createComponent({
           propsData: {
             formTouched: true,
           },
           stubs: { GlModal },
         });
-      });
 
-      it('asks the user to confirm the action', () => {
-        jest.spyOn(findCancelModal().vm, 'show').mockReturnValue();
+        await waitForPromises();
+
+        const toggleModalMock = jest.spyOn(resolvers.Mutation, 'toggleModal').mockReturnValue();
         findCancelButton().vm.$emit('click');
 
-        expect(findCancelModal().vm.show).toHaveBeenCalled();
+        await waitForPromises();
+
+        expect(toggleModalMock).toHaveBeenCalled();
       });
 
-      it('emits cancel event upon confirming', () => {
-        findCancelModal().vm.$emit('ok');
+      it('emits cancel event upon confirming', async () => {
+        createComponent({
+          propsData: {
+            formTouched: false,
+          },
+          stubs: { GlModal },
+        });
+        await waitForPromises();
+
+        findCancelModal().vm.$emit('primary');
+        await waitForPromises();
 
         expect(wrapper.emitted('cancel')).toHaveLength(1);
       });
diff --git a/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator_spec.js b/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator_spec.js
index bf5acae678fbe80461844a3563260fa20e83d3ab..106630ce38e54fb14e90ceb23ca6370d3f0fff63 100644
--- a/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator_spec.js
+++ b/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_configurator/dast_profiles_configurator_spec.js
@@ -1,7 +1,6 @@
 import { merge } from 'lodash';
 import { GlLink } from '@gitlab/ui';
 import VueApollo from 'vue-apollo';
-import { nextTick } from 'vue';
 import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
 import siteProfilesFixtures from 'test_fixtures/graphql/security_configuration/dast_profiles/graphql/dast_site_profiles.query.graphql.basic.json';
 import scannerProfilesFixtures from 'test_fixtures/graphql/security_configuration/dast_profiles/graphql/dast_scanner_profiles.query.graphql.basic.json';
@@ -18,6 +17,9 @@ import SectionLayout from '~/vue_shared/security_configuration/components/sectio
 import SectionLoader from '~/vue_shared/security_configuration/components/section_loader.vue';
 import dastScannerProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_scanner_profiles.query.graphql';
 import dastSiteProfilesQuery from 'ee/security_configuration/dast_profiles/graphql/dast_site_profiles.query.graphql';
+import resolvers from 'ee/vue_shared/security_configuration/graphql/resolvers/resolvers';
+import { typePolicies } from 'ee/vue_shared/security_configuration/graphql/provider';
+import waitForPromises from 'helpers/wait_for_promises';
 import createApolloProvider from 'helpers/mock_apollo_helper';
 import { extendedWrapper } from 'helpers/vue_test_utils_helper';
 import {
@@ -31,21 +33,27 @@ describe('DastProfilesConfigurator', () => {
   let requestHandlers;
   const projectPath = 'projectPath';
 
-  const createMockApolloProvider = (handlers) => {
+  const createMockApolloProvider = () => {
     localVue.use(VueApollo);
 
     requestHandlers = {
       dastScannerProfiles: jest.fn().mockResolvedValue(scannerProfilesFixtures),
       dastSiteProfiles: jest.fn().mockResolvedValue(siteProfilesFixtures),
-      ...handlers,
     };
 
-    return createApolloProvider([
-      [dastScannerProfilesQuery, requestHandlers.dastScannerProfiles],
-      [dastSiteProfilesQuery, requestHandlers.dastSiteProfiles],
-    ]);
+    return createApolloProvider(
+      [
+        [dastScannerProfilesQuery, requestHandlers.dastScannerProfiles],
+        [dastSiteProfilesQuery, requestHandlers.dastSiteProfiles],
+      ],
+      resolvers,
+      { typePolicies },
+    );
   };
 
+  const findModal = () => wrapper.findByTestId('dast-profile-form-cancel-modal');
+  const findProfileNameInput = () => wrapper.findByTestId('profile-name-input');
+  const findEditBtn = () => wrapper.findByTestId('profile-edit-btn');
   const findNewScanButton = () => wrapper.findByTestId('new-profile-button');
   const findOpenDrawerButton = () => wrapper.findByTestId('select-profile-action-btn');
   const findCancelButton = () => wrapper.findByTestId('dast-profile-form-cancel-button');
@@ -62,25 +70,14 @@ describe('DastProfilesConfigurator', () => {
 
   const openDrawer = async () => {
     findOpenDrawerButton().vm.$emit('click');
-    await nextTick();
+    await waitForPromises();
   };
 
-  const createComponentFactory = (mountFn = shallowMount) => (options = {}, withHandlers) => {
+  const createComponentFactory = (mountFn = shallowMount) => (options = {}) => {
     localVue = createLocalVue();
-    let defaultMocks = {
-      $apollo: {
-        mutate: jest.fn(),
-        queries: {
-          scannerProfiles: jest.fn(),
-          siteProfiles: jest.fn(),
-        },
-      },
-    };
-    let apolloProvider;
-    if (withHandlers) {
-      apolloProvider = createMockApolloProvider(withHandlers);
-      defaultMocks = {};
-    }
+
+    const apolloProvider = createMockApolloProvider();
+
     wrapper = extendedWrapper(
       mountFn(
         DastProfilesConfigurator,
@@ -90,18 +87,17 @@ describe('DastProfilesConfigurator', () => {
             propsData: {
               ...options,
             },
-            mocks: defaultMocks,
             stubs: {
               SectionLayout,
               ScannerProfileSelector,
               SiteProfileSelector,
+              GlModal: true,
             },
             provide: {
               projectPath,
             },
           },
           { ...options, localVue, apolloProvider },
-
           {
             data() {
               return {
@@ -125,9 +121,10 @@ describe('DastProfilesConfigurator', () => {
   });
 
   describe('when default state', () => {
-    it('renders properly', () => {
+    it('renders properly', async () => {
       const sectionHeader = s__('OnDemandScans|DAST configuration');
       createComponent({ configurationHeader: sectionHeader });
+      await waitForPromises();
 
       expect(findSectionLayout().find('h2').text()).toContain(sectionHeader);
       expect(findScannerProfilesSelector().exists()).toBe(true);
@@ -144,40 +141,22 @@ describe('DastProfilesConfigurator', () => {
       );
     });
 
-    it.each`
-      scannerProfilesLoading | siteProfilesLoading | isLoading
-      ${true}                | ${true}             | ${true}
-      ${false}               | ${true}             | ${true}
-      ${true}                | ${false}            | ${true}
-      ${false}               | ${false}            | ${false}
-    `(
-      'sets loading state to $isLoading if scanner profiles loading is $scannerProfilesLoading and site profiles loading is $siteProfilesLoading',
-      ({ scannerProfilesLoading, siteProfilesLoading, isLoading }) => {
-        createShallowComponent({
-          mocks: {
-            $apollo: {
-              queries: {
-                scannerProfiles: { loading: scannerProfilesLoading },
-                siteProfiles: { loading: siteProfilesLoading },
-              },
-            },
-          },
-        });
+    it('shows loader in loading state', () => {
+      createShallowComponent();
 
-        expect(findSectionLoader().exists()).toBe(isLoading);
-      },
-    );
+      expect(findSectionLoader().exists()).toBe(true);
+    });
   });
 
   describe('profile drawer', () => {
-    beforeEach(() => {
-      createComponent();
+    beforeEach(async () => {
+      createComponent({}, true);
+      await waitForPromises();
     });
 
     it('should open drawer with scanner profiles', async () => {
       findScannerProfilesSelector().vm.$emit('open-drawer');
-
-      await nextTick();
+      await waitForPromises();
 
       expect(findDastProfileSidebar().exists()).toBe(true);
       expect(findAllScannerProfileSummary()).toHaveLength(scannerProfiles.length);
@@ -185,8 +164,7 @@ describe('DastProfilesConfigurator', () => {
 
     it('should open drawer with site profiles', async () => {
       findSiteProfilesSelector().vm.$emit('open-drawer');
-
-      await nextTick();
+      await waitForPromises();
 
       expect(findDastProfileSidebar().exists()).toBe(true);
       expect(findAllSiteProfileSummary()).toHaveLength(siteProfiles.length);
@@ -199,8 +177,9 @@ describe('DastProfilesConfigurator', () => {
       dastSiteProfile: { id: siteProfiles[0].id },
     };
 
-    it('should have profiles selected if saved profiles exist', () => {
+    it('should have profiles selected if saved profiles exist', async () => {
       createComponent({ savedProfiles });
+      await waitForPromises();
 
       expect(findScannerProfilesSelector().find('h3').text()).toContain(
         scannerProfiles[0].profileName,
@@ -215,7 +194,7 @@ describe('DastProfilesConfigurator', () => {
 
     beforeEach(async () => {
       createComponent({ savedSiteProfileName, savedScannerProfileName }, true);
-      await nextTick();
+      await waitForPromises();
     });
 
     it('should have saved profiles selected', async () => {
@@ -230,13 +209,14 @@ describe('DastProfilesConfigurator', () => {
   });
 
   describe('switching between modes', () => {
-    beforeEach(() => {
-      createComponent();
+    beforeEach(async () => {
+      createComponent({}, true);
+      await waitForPromises();
     });
 
     const expectEditingMode = async () => {
       findNewScanButton().vm.$emit('click');
-      await nextTick();
+      await waitForPromises();
       expect(findDastProfilesSidebarForm().exists()).toBe(true);
     };
 
@@ -256,9 +236,35 @@ describe('DastProfilesConfigurator', () => {
       await expectEditingMode();
 
       findCancelButton().vm.$emit('click');
-      await nextTick();
+      await waitForPromises();
 
       expect(findDastProfilesSidebarList().exists()).toBe(true);
     });
   });
+
+  describe('warning modal', () => {
+    beforeEach(async () => {
+      createComponent({}, true);
+      await waitForPromises();
+    });
+
+    it('should show warning modal when changes are unsaved', async () => {
+      const mutateMock = jest.spyOn(wrapper.vm.$apollo, 'mutate');
+
+      findOpenDrawerButton().vm.$emit('click');
+      await waitForPromises();
+
+      findEditBtn().vm.$emit('click');
+      await waitForPromises();
+
+      findProfileNameInput().vm.$emit('input', 'another value');
+      await waitForPromises();
+
+      findOpenDrawerButton().vm.$emit('click');
+      await waitForPromises();
+
+      expect(findModal().attributes('visible')).toEqual(String(true));
+      expect(mutateMock).toHaveBeenCalledTimes(3);
+    });
+  });
 });
diff --git a/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar_spec.js b/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar_spec.js
index dce4c9954633503eda6404a80b6823b9b4bececc..e25f906147a08a1c75670ae430b3e6c0dcec8e56 100644
--- a/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar_spec.js
+++ b/ee/spec/frontend/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar_spec.js
@@ -1,24 +1,39 @@
 import { GlDrawer, GlLink } from '@gitlab/ui';
-import { nextTick } from 'vue';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
 import { __ } from '~/locale';
 import { mountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
 import DastProfilesSidebar from 'ee/security_configuration/dast_profiles/dast_profiles_sidebar/dast_profiles_sidebar.vue';
 import DastProfilesLoader from 'ee/security_configuration/dast_profiles/components/dast_profiles_loader.vue';
-import { scannerProfiles } from 'ee_jest/security_configuration/dast_profiles/mocks/mock_data';
-import { SCANNER_TYPE, SITE_TYPE, SIDEBAR_VIEW_MODE } from 'ee/on_demand_scans/constants';
+import {
+  scannerProfiles,
+  mockSharedData,
+} from 'ee_jest/security_configuration/dast_profiles/mocks/mock_data';
+import { SCANNER_TYPE, SIDEBAR_VIEW_MODE } from 'ee/on_demand_scans/constants';
+import resolvers from 'ee/vue_shared/security_configuration/graphql/resolvers/resolvers';
+import { typePolicies } from 'ee/vue_shared/security_configuration/graphql/provider';
 
 describe('DastProfilesSidebar', () => {
   let wrapper;
+  let fakeApollo;
   const projectPath = 'projectPath';
   const libraryLink = 'libraryLink';
 
+  Vue.use(VueApollo);
+
   const createComponent = (options = {}) => {
+    fakeApollo = createMockApollo([], resolvers, { typePolicies });
+
     wrapper = mountExtended(DastProfilesSidebar, {
+      apolloProvider: fakeApollo,
       propsData: {
         ...options,
       },
       stubs: {
         GlDrawer: true,
+        GlModal: true,
       },
       provide: {
         projectPath,
@@ -26,6 +41,9 @@ describe('DastProfilesSidebar', () => {
     });
   };
 
+  const findProfileNameInput = () => wrapper.findByTestId('profile-name-input');
+  const findModal = () => wrapper.findByTestId('dast-profile-form-cancel-modal');
+  const findEditButton = () => wrapper.findByTestId('profile-edit-btn');
   const findSidebarHeader = () => wrapper.findByTestId('sidebar-header');
   const findEmptyStateHeader = () => wrapper.findByTestId('empty-state-header');
   const findNewScanButton = () => wrapper.findByTestId('new-profile-button');
@@ -36,70 +54,61 @@ describe('DastProfilesSidebar', () => {
   const findSkeletonLoader = () => wrapper.findComponent(DastProfilesLoader);
   const findGlDrawer = () => wrapper.findComponent(GlDrawer);
 
+  const openEditForm = async () => {
+    findEditButton().vm.$emit('click');
+    await waitForPromises();
+  };
+
   afterEach(() => {
-    wrapper.destroy();
+    mockSharedData.history = [];
   });
 
-  describe.each`
-    scannerType     | header       | expectedResult
-    ${SCANNER_TYPE} | ${'Scanner'} | ${SCANNER_TYPE}
-    ${SITE_TYPE}    | ${'Site'}    | ${SITE_TYPE}
-  `('should emit correct event', ({ scannerType, header, expectedResult }) => {
-    createComponent({ profileType: scannerType });
+  it('should render empty state', async () => {
+    createComponent();
+
+    await waitForPromises();
+
     expect(findEmptyStateHeader().exists()).toBe(true);
-    expect(findEmptyStateHeader().text()).toContain(`No ${expectedResult} profiles found for DAST`);
-    expect(findSidebarHeader().text()).toContain(`${header} profile library`);
+    expect(findEmptyStateHeader().text()).toContain(`No ${SCANNER_TYPE} profiles found for DAST`);
+    expect(findSidebarHeader().text()).toContain('Scanner profile library');
   });
 
-  it('should render new scan button when profiles exists', () => {
+  it('should render new scan button when profiles exists', async () => {
     createComponent({ profiles: scannerProfiles });
+    await waitForPromises();
     expect(findNewScanButton().exists()).toBe(true);
   });
 
-  it('should hide new scan button when no profiles exists', () => {
+  it('should hide new scan button when no profiles exists', async () => {
     createComponent();
-
+    await waitForPromises();
     expect(findNewScanButton().exists()).toBe(false);
   });
 
-  it('should open new scanner profile form when in editing mode', async () => {
-    createComponent({
-      profileType: SCANNER_TYPE,
-      profiles: scannerProfiles,
-      sidebarViewMode: SIDEBAR_VIEW_MODE.EDITING_MODE,
-    });
-
-    await nextTick();
-
-    expect(findNewDastScannerProfileForm().exists()).toBe(true);
-    expect(findSidebarHeader().text()).toContain('New scanner profile');
-  });
-
   describe('new profile form', () => {
-    describe.each`
-      scannerType     | expectedResult
-      ${SCANNER_TYPE} | ${SCANNER_TYPE}
-      ${SITE_TYPE}    | ${SITE_TYPE}
-    `('should emit correct event', ({ scannerType, expectedResult }) => {
-      createComponent({ profileType: scannerType });
+    it('should emit correct event', async () => {
+      createComponent();
+      await waitForPromises();
+
       findEmptyNewScanButton().vm.$emit('click');
+      await waitForPromises();
 
       expect(wrapper.emitted()).toEqual({
-        'reopen-drawer': [[{ mode: SIDEBAR_VIEW_MODE.EDITING_MODE, profileType: expectedResult }]],
+        'reopen-drawer': [[{ mode: SIDEBAR_VIEW_MODE.EDITING_MODE, profileType: SCANNER_TYPE }]],
       });
       expect(findNewScanButton().exists()).toBe(false);
     });
 
     it('should close form when cancelled', async () => {
-      createComponent({ profileType: SITE_TYPE, sidebarViewMode: SIDEBAR_VIEW_MODE.EDITING_MODE });
+      createComponent({ profiles: scannerProfiles });
+      await waitForPromises();
 
-      findCancelButton().vm.$emit('click');
+      await openEditForm();
 
-      await nextTick();
+      findCancelButton().vm.$emit('click');
+      await waitForPromises();
 
-      expect(wrapper.emitted()).toEqual({
-        'reopen-drawer': [[{ mode: SIDEBAR_VIEW_MODE.READING_MODE, profileType: SITE_TYPE }]],
-      });
+      expect(wrapper.emitted()['close-drawer']).toBeTruthy();
     });
   });
 
@@ -113,12 +122,11 @@ describe('DastProfilesSidebar', () => {
   describe('editing mode', () => {
     it('should be possible to edit profile', async () => {
       createComponent({
-        profileType: SCANNER_TYPE,
         profiles: scannerProfiles,
-        sidebarViewMode: SIDEBAR_VIEW_MODE.EDITING_MODE,
       });
-      wrapper.setProps({ activeProfile: scannerProfiles[0] });
-      await nextTick();
+      await waitForPromises();
+
+      await openEditForm();
 
       expect(findNewDastScannerProfileForm().exists()).toBe(true);
       expect(findNewScanButton().exists()).toBe(false);
@@ -127,36 +135,108 @@ describe('DastProfilesSidebar', () => {
   });
 
   describe('sticky header', () => {
-    it('should have sticky header always enabled', () => {
+    it('should have sticky header always enabled', async () => {
       createComponent();
+      await waitForPromises();
 
-      expect(findGlDrawer().props('headerSticky')).toEqual(true);
+      expect(findGlDrawer().props('headerSticky')).toBe(true);
     });
   });
 
   describe('sticky footer', () => {
-    it.each`
-      profileType     | expectedResult
-      ${SCANNER_TYPE} | ${__(`Manage ${SCANNER_TYPE} profiles`)}
-      ${SITE_TYPE}    | ${__(`Manage ${SITE_TYPE} profiles`)}
-    `('renders correctly for $profileType profiles', ({ profileType, expectedResult }) => {
-      createComponent({ profileType, libraryLink });
-
-      expect(findFooterLink().text()).toBe(expectedResult);
+    it('renders correctly', async () => {
+      createComponent({ libraryLink });
+      await waitForPromises();
+
+      expect(findFooterLink().text()).toBe(__(`Manage ${SCANNER_TYPE} profiles`));
       expect(findFooterLink().attributes('href')).toEqual(libraryLink);
     });
 
-    it.each`
-      sidebarViewMode                   | expectedResult
-      ${SIDEBAR_VIEW_MODE.READING_MODE} | ${true}
-      ${SIDEBAR_VIEW_MODE.EDITING_MODE} | ${false}
-    `(
-      'should set footer visibility as $expectedResult for $sidebarViewMode mode',
-      ({ sidebarViewMode, expectedResult }) => {
-        createComponent({ profiles: scannerProfiles, sidebarViewMode, libraryLink });
+    it('should have footer in reading mode', async () => {
+      createComponent({ profiles: scannerProfiles, libraryLink });
+      await waitForPromises();
 
-        expect(findFooterLink().exists()).toBe(expectedResult);
-      },
-    );
+      expect(findFooterLink().exists()).toBe(true);
+    });
+
+    it('should have footer hidden in editing mode', async () => {
+      createComponent({ profiles: scannerProfiles, libraryLink });
+      await waitForPromises();
+
+      await openEditForm();
+
+      expect(findFooterLink().exists()).toBe(false);
+    });
+  });
+
+  describe('warning modal', () => {
+    it('should show modal on cancel if there are unsaved changes', async () => {
+      const showModalMock = jest.spyOn(resolvers.Mutation, 'toggleModal');
+      createComponent({ profiles: scannerProfiles });
+      await waitForPromises();
+
+      await openEditForm();
+
+      findProfileNameInput().vm.$emit('input', 'another value');
+      await waitForPromises();
+
+      findCancelButton().vm.$emit('click');
+      await waitForPromises();
+
+      expect(findModal().attributes('visible')).toEqual(String(true));
+      expect(showModalMock).toHaveBeenCalledTimes(1);
+    });
+
+    it('should show modal before closing drawer if there are unsaved changes', async () => {
+      const showModalMock = jest.spyOn(resolvers.Mutation, 'toggleModal');
+      createComponent({ profiles: scannerProfiles });
+      await waitForPromises();
+
+      await openEditForm();
+
+      findProfileNameInput().vm.$emit('input', 'another value');
+      await waitForPromises();
+
+      findGlDrawer().vm.$emit('close');
+      await waitForPromises();
+
+      expect(findModal().attributes('visible')).toEqual(String(true));
+      expect(showModalMock).toHaveBeenCalledTimes(1);
+    });
+
+    it('should reset state history and close drawer if there are no unsaved changes', async () => {
+      const resetHistoryMock = jest.spyOn(resolvers.Mutation, 'resetHistory');
+      createComponent({ profiles: scannerProfiles });
+      await waitForPromises();
+
+      findGlDrawer().vm.$emit('close');
+      await waitForPromises();
+
+      expect(resetHistoryMock).toHaveBeenCalledTimes(1);
+      expect(wrapper.emitted()['close-drawer']).toBeTruthy();
+    });
+
+    it('should discard changes from warning modal', async () => {
+      const goBackMock = jest.spyOn(resolvers.Mutation, 'goBack');
+      const setCachedPayloadMock = jest.spyOn(resolvers.Mutation, 'setCachedPayload');
+      createComponent({ profiles: scannerProfiles });
+      await waitForPromises();
+
+      await openEditForm();
+
+      findProfileNameInput().vm.$emit('input', 'another value');
+      await waitForPromises();
+
+      findGlDrawer().vm.$emit('close');
+      await waitForPromises();
+
+      findModal().vm.$emit('primary');
+      await waitForPromises();
+
+      expect(findModal().exists()).toBe(false);
+      expect(goBackMock).toHaveBeenCalledTimes(1);
+      expect(setCachedPayloadMock).toHaveBeenCalledTimes(1);
+      expect(wrapper.emitted()['close-drawer']).toBeTruthy();
+    });
   });
 });
diff --git a/ee/spec/frontend/security_configuration/dast_profiles/dast_site_profiles/components/dast_site_profile_form_spec.js b/ee/spec/frontend/security_configuration/dast_profiles/dast_site_profiles/components/dast_site_profile_form_spec.js
index e6d0bfc767ef9ca4c7e1678153b3e9a0d5c6488b..9a5cc5ee2fb1d29ebb87d9a310c3ae167a90bb24 100644
--- a/ee/spec/frontend/security_configuration/dast_profiles/dast_site_profiles/components/dast_site_profile_form_spec.js
+++ b/ee/spec/frontend/security_configuration/dast_profiles/dast_site_profiles/components/dast_site_profile_form_spec.js
@@ -1,3 +1,5 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
 import { GlForm } from '@gitlab/ui';
 import { within } from '@testing-library/dom';
 import merge from 'lodash/merge';
@@ -8,7 +10,11 @@ import DastSiteProfileForm from 'ee/security_configuration/dast_profiles/dast_si
 import dastSiteProfileCreateMutation from 'ee/security_configuration/dast_profiles/dast_site_profiles/graphql/dast_site_profile_create.mutation.graphql';
 import dastSiteProfileUpdateMutation from 'ee/security_configuration/dast_profiles/dast_site_profiles/graphql/dast_site_profile_update.mutation.graphql';
 import { policySiteProfiles } from 'ee_jest/security_configuration/dast_profiles/mocks/mock_data';
+import resolvers from 'ee/vue_shared/security_configuration/graphql/resolvers/resolvers';
+import { typePolicies } from 'ee/vue_shared/security_configuration/graphql/provider';
 import { TEST_HOST } from 'helpers/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
+import createMockApollo from 'helpers/mock_apollo_helper';
 import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
 import {
   SCAN_METHODS,
@@ -30,6 +36,8 @@ const defaultProps = {
   projectFullPath,
 };
 
+Vue.use(VueApollo);
+
 describe('DastSiteProfileForm', () => {
   let wrapper;
 
@@ -79,13 +87,18 @@ describe('DastSiteProfileForm', () => {
     return radio.trigger('change');
   };
 
-  const createComponentFactory = (mountFn = mountExtended) => (options) => {
+  const createComponentFactory = (mountFn = mountExtended) => (options = {}) => {
+    const apolloProvider = createMockApollo([], resolvers, { typePolicies });
+
     const mountOpts = merge(
       {},
       {
         propsData: defaultProps,
         provide: { glFeatures: { dastApiScanner: true } },
       },
+      {
+        apolloProvider,
+      },
       options,
     );
 
@@ -119,8 +132,9 @@ describe('DastSiteProfileForm', () => {
   describe('target URL input', () => {
     const errorMessage = 'Please enter a valid URL format, ex: http://www.example.com/home';
 
-    beforeEach(() => {
+    beforeEach(async () => {
       createComponent();
+      await waitForPromises();
     });
 
     it.each(['asd', 'example.com'])(
@@ -140,8 +154,9 @@ describe('DastSiteProfileForm', () => {
   });
 
   describe('additional fields', () => {
-    beforeEach(() => {
+    beforeEach(async () => {
       createComponent();
+      await waitForPromises();
     });
 
     it('should render correctly with default values', () => {
@@ -246,12 +261,13 @@ describe('DastSiteProfileForm', () => {
         ${'New site profile'}  | ${{}}                     | ${{ fullPath: projectFullPath }}     | ${dastSiteProfileCreateMutation} | ${'dastSiteProfileCreate'}
         ${'Edit site profile'} | ${siteProfileWithSecrets} | ${{ id: siteProfileWithSecrets.id }} | ${dastSiteProfileUpdateMutation} | ${'dastSiteProfileUpdate'}
       `('$title', ({ profile, mutationVars, mutation, mutationKind }) => {
-        beforeEach(() => {
+        beforeEach(async () => {
           createComponent({
             propsData: {
               profile,
             },
           });
+          await waitForPromises();
         });
 
         it('passes correct props to base component', async () => {
diff --git a/ee/spec/frontend/security_configuration/dast_profiles/mocks/mock_data.js b/ee/spec/frontend/security_configuration/dast_profiles/mocks/mock_data.js
index a881419706139b6e26855ee58d9d02aa3a432f2f..f8c0ac60ed3a244f3a05dfbf04ddfee7d6a08329 100644
--- a/ee/spec/frontend/security_configuration/dast_profiles/mocks/mock_data.js
+++ b/ee/spec/frontend/security_configuration/dast_profiles/mocks/mock_data.js
@@ -22,3 +22,16 @@ export const scannerProfiles = scannerProfilesFixtures.data.project.scannerProfi
 
 export const failedSiteValidations =
   dastFailedSiteValidationsFixtures.data.project.validations.nodes;
+
+export const mockSharedData = {
+  showDiscardChangesModal: false,
+  formTouched: false,
+  history: [],
+  cashedPayload: {
+    __typename: 'CachedPayload',
+    profileType: '',
+    mode: '',
+  },
+  resetAndClose: false,
+  __typename: 'SharedData',
+};
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ab1356dd35c521b863e96303c2749ae7b93a9aa6..e46cf7594106cb72967c461527c8f83f362c662b 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -11894,15 +11894,6 @@ msgstr ""
 msgid "DastProfiles|Delete profile"
 msgstr ""
 
-msgid "DastProfiles|Do you want to discard this scanner profile?"
-msgstr ""
-
-msgid "DastProfiles|Do you want to discard this site profile?"
-msgstr ""
-
-msgid "DastProfiles|Do you want to discard your changes?"
-msgstr ""
-
 msgid "DastProfiles|Edit profile"
 msgstr ""
 
@@ -27282,6 +27273,12 @@ msgstr ""
 msgid "OnDemandScans|Description (optional)"
 msgstr ""
 
+msgid "OnDemandScans|Discard changes"
+msgstr ""
+
+msgid "OnDemandScans|Do you want to discard the changes or keep editing this profile? Unsaved changes will be lost."
+msgstr ""
+
 msgid "OnDemandScans|Dynamic Application Security Testing (DAST)"
 msgstr ""
 
@@ -27303,6 +27300,9 @@ msgstr ""
 msgid "OnDemandScans|For example: Tests the login page for SQL injections"
 msgstr ""
 
+msgid "OnDemandScans|Keep editing"
+msgstr ""
+
 msgid "OnDemandScans|Manage scanner profiles"
 msgstr ""
 
@@ -27426,6 +27426,9 @@ msgstr ""
 msgid "OnDemandScans|View results"
 msgstr ""
 
+msgid "OnDemandScans|You have unsaved changes"
+msgstr ""
+
 msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
 msgstr ""