diff --git a/ee/app/assets/javascripts/security_orchestration/components/policy_editor/vulnerability_management/editor_component.vue b/ee/app/assets/javascripts/security_orchestration/components/policy_editor/vulnerability_management/editor_component.vue
index f28d8cdee24722482a8fa705a9ea5baddce1d304..273bf041eb9686c4f2ce287e309adb35b3ab32fb 100644
--- a/ee/app/assets/javascripts/security_orchestration/components/policy_editor/vulnerability_management/editor_component.vue
+++ b/ee/app/assets/javascripts/security_orchestration/components/policy_editor/vulnerability_management/editor_component.vue
@@ -7,6 +7,7 @@ import {
   EDITOR_MODE_RULE,
   EDITOR_MODE_YAML,
   PARSING_ERROR_MESSAGE,
+  SECURITY_POLICY_ACTIONS,
 } from '../constants';
 import EditorLayout from '../editor_layout.vue';
 import DimDisableContainer from '../dim_disable_container.vue';
@@ -16,6 +17,7 @@ import RuleSection from './rule/rule_section.vue';
 import ActionSection from './action/action_section.vue';
 
 export default {
+  SECURITY_POLICY_ACTIONS,
   EDITOR_MODE_RULE,
   EDITOR_MODE_YAML,
   i18n: {
@@ -41,6 +43,14 @@ export default {
       required: false,
       default: null,
     },
+    isCreating: {
+      type: Boolean,
+      required: true,
+    },
+    isDeleting: {
+      type: Boolean,
+      required: true,
+    },
     isEditing: {
       type: Boolean,
       required: true,
@@ -62,16 +72,28 @@ export default {
       mode: EDITOR_MODE_RULE,
       policy,
       yamlEditorValue,
-      isUpdatingPolicy: false,
-      isRemovingPolicy: false,
       hasParsingError,
       parsingError,
     };
   },
+  computed: {
+    policyActionName() {
+      return this.isEditing
+        ? this.$options.SECURITY_POLICY_ACTIONS.REPLACE
+        : this.$options.SECURITY_POLICY_ACTIONS.APPEND;
+    },
+  },
   methods: {
     changeEditorMode(mode) {
       this.mode = mode;
     },
+    async handleModifyPolicy(act) {
+      // Assumes feature flag securityPoliciesProjectBackgroundWorker is enabled
+      this.$emit('save', {
+        action: act || this.policyActionName,
+        policy: this.yamlEditorValue,
+      });
+    },
     handleUpdateProperty(property, value) {
       this.policy[property] = value;
       this.updateYamlEditorValue(this.policy);
@@ -107,10 +129,12 @@ export default {
     :policy="policy"
     :yaml-editor-value="yamlEditorValue"
     :is-editing="isEditing"
-    :is-removing-policy="isRemovingPolicy"
-    :is-updating-policy="isUpdatingPolicy"
+    :is-removing-policy="isDeleting"
+    :is-updating-policy="isCreating"
     :has-parsing-error="hasParsingError"
     :parsing-error="parsingError"
+    @remove-policy="handleModifyPolicy($options.SECURITY_POLICY_ACTIONS.REMOVE)"
+    @save-policy="handleModifyPolicy()"
     @update-editor-mode="changeEditorMode"
     @update-property="handleUpdateProperty"
     @update-yaml="handleUpdateYaml"
diff --git a/ee/spec/frontend/security_orchestration/components/policy_editor/vulnerability_management/editor_component_spec.js b/ee/spec/frontend/security_orchestration/components/policy_editor/vulnerability_management/editor_component_spec.js
index e2e0e6acc612e51625793076eeb6d4ffb002afb7..76789df3c78fd3409ea06ce5ef4e0c7108f274d4 100644
--- a/ee/spec/frontend/security_orchestration/components/policy_editor/vulnerability_management/editor_component_spec.js
+++ b/ee/spec/frontend/security_orchestration/components/policy_editor/vulnerability_management/editor_component_spec.js
@@ -1,4 +1,5 @@
 import { nextTick } from 'vue';
+import waitForPromises from 'helpers/wait_for_promises';
 import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
 import { DEFAULT_ASSIGNED_POLICY_PROJECT } from 'ee/security_orchestration/constants';
 import EditorComponent from 'ee/security_orchestration/components/policy_editor/vulnerability_management/editor_component.vue';
@@ -6,6 +7,9 @@ import EditorLayout from 'ee/security_orchestration/components/policy_editor/edi
 import RuleSection from 'ee/security_orchestration/components/policy_editor/vulnerability_management/rule/rule_section.vue';
 import ActionSection from 'ee/security_orchestration/components/policy_editor/vulnerability_management/action/action_section.vue';
 import { DEFAULT_VULNERABILITY_MANAGEMENT_POLICY } from 'ee/security_orchestration/components/policy_editor/vulnerability_management/constants';
+
+import { SECURITY_POLICY_ACTIONS } from 'ee/security_orchestration/components/policy_editor/constants';
+import { ASSIGNED_POLICY_PROJECT } from 'ee_jest/security_orchestration/mocks/mock_data';
 import {
   mockVulnerabilityManagementManifest,
   mockVulnerabilityManagementObject,
@@ -19,6 +23,8 @@ describe('EditorComponent', () => {
     wrapper = shallowMountExtended(EditorComponent, {
       propsData: {
         assignedPolicyProject: DEFAULT_ASSIGNED_POLICY_PROJECT,
+        isCreating: false,
+        isDeleting: false,
         isEditing: false,
         ...propsData,
       },
@@ -29,6 +35,16 @@ describe('EditorComponent', () => {
     });
   };
 
+  const factoryWithExistingPolicy = () => {
+    return factory({
+      propsData: {
+        assignedPolicyProject: ASSIGNED_POLICY_PROJECT,
+        existingPolicy: mockVulnerabilityManagementObject,
+        isEditing: true,
+      },
+    });
+  };
+
   const findPolicyEditorLayout = () => wrapper.findComponent(EditorLayout);
   const findRuleSection = () => wrapper.findComponent(RuleSection);
   const findAllRuleSections = () => wrapper.findAllComponents(RuleSection);
@@ -124,4 +140,18 @@ describe('EditorComponent', () => {
       );
     });
   });
+
+  describe('modifying a policy', () => {
+    it.each`
+      status                           | action                             | event              | factoryFn                    | yamlEditorValue
+      ${'creating a new policy'}       | ${SECURITY_POLICY_ACTIONS.APPEND}  | ${'save-policy'}   | ${factory}                   | ${DEFAULT_VULNERABILITY_MANAGEMENT_POLICY}
+      ${'updating an existing policy'} | ${SECURITY_POLICY_ACTIONS.REPLACE} | ${'save-policy'}   | ${factoryWithExistingPolicy} | ${mockVulnerabilityManagementManifest}
+      ${'deleting an existing policy'} | ${SECURITY_POLICY_ACTIONS.REMOVE}  | ${'remove-policy'} | ${factoryWithExistingPolicy} | ${mockVulnerabilityManagementManifest}
+    `('emits "save" when $status', async ({ action, event, factoryFn, yamlEditorValue }) => {
+      factoryFn();
+      findPolicyEditorLayout().vm.$emit(event);
+      await waitForPromises();
+      expect(wrapper.emitted('save')).toEqual([[{ action, policy: yamlEditorValue }]]);
+    });
+  });
 });
diff --git a/ee/spec/frontend/security_orchestration/mocks/mock_vulnerability_management_policy_data.js b/ee/spec/frontend/security_orchestration/mocks/mock_vulnerability_management_policy_data.js
index 8ca7115b33671a7ffe5d0effcd669a98c3bb8a9f..a7387e811656a5d64666a4cb153a9fe482f245c0 100644
--- a/ee/spec/frontend/security_orchestration/mocks/mock_vulnerability_management_policy_data.js
+++ b/ee/spec/frontend/security_orchestration/mocks/mock_vulnerability_management_policy_data.js
@@ -24,11 +24,16 @@ actions:
   - type: auto_resolve
 rules:
   - type: no_longer_detected
-    scanners: ["sast", "dependency_scanning"]
-    severity_levels: ["high", "medium"]
+    scanners:
+      - sast
+      - dependency_scanning
+    severity_levels:
+      - high
+      - medium
   - type: no_longer_detected
     scanners: []
-    severity_levels: ["low"]
+    severity_levels:
+      - low
 `;
 
 export const mockVulnerabilityManagementObject = fromYaml({