diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index fd713a7a50439a0f6287ac42aa611797e83f31f2..da213b0ed43072c07eff8a79704e53e17761d1c9 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -1,5 +1,6 @@
 import { helpPagePath } from '~/helpers/help_page_helper';
 import { __, s__ } from '~/locale';
+import ContinuousVulnerabilityScan from '~/security_configuration/components/continuous_vulnerability_scan.vue';
 
 import {
   REPORT_TYPE_SAST,
@@ -210,6 +211,7 @@ export const securityFeatures = [
     configurationHelpPath: DEPENDENCY_SCANNING_CONFIG_HELP_PATH,
     type: REPORT_TYPE_DEPENDENCY_SCANNING,
     anchor: 'dependency-scanning',
+    slotComponent: ContinuousVulnerabilityScan,
   },
   {
     name: CONTAINER_SCANNING_NAME,
diff --git a/app/assets/javascripts/security_configuration/components/continuous_vulnerability_scan.vue b/app/assets/javascripts/security_configuration/components/continuous_vulnerability_scan.vue
new file mode 100644
index 0000000000000000000000000000000000000000..61cbde2107c0a90a2e9d4e8b52764088d82a3447
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/continuous_vulnerability_scan.vue
@@ -0,0 +1,127 @@
+<script>
+import { GlBadge, GlIcon, GlToggle, GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
+import ProjectSetContinuousVulnerabilityScanning from '~/security_configuration/graphql/project_set_continuous_vulnerability_scanning.graphql';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { __, s__ } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+export default {
+  name: 'ContinuousVulnerabilityscan',
+  components: { GlBadge, GlIcon, GlToggle, GlLink, GlSprintf, GlAlert },
+  mixins: [glFeatureFlagsMixin()],
+  inject: ['continuousVulnerabilityScansEnabled', 'projectFullPath'],
+  i18n: {
+    badgeLabel: __('Experiment'),
+    title: s__('CVS|Continuous Vulnerability Scan'),
+    description: s__(
+      'CVS|Detect vulnerabilities outside a pipeline as new data is added to the GitLab Advisory Database.',
+    ),
+    learnMore: __('Learn more'),
+    testingAgreementMessage: s__(
+      'CVS|By enabling this feature, you accept the %{linkStart}Testing Terms of Use%{linkEnd}',
+    ),
+  },
+  props: {
+    feature: {
+      type: Object,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      toggleValue: this.continuousVulnerabilityScansEnabled,
+      errorMessage: '',
+      isAlertDismissed: false,
+    };
+  },
+  computed: {
+    isFeatureConfigured() {
+      return this.feature.available && this.feature.configured;
+    },
+    shouldShowAlert() {
+      return this.errorMessage && !this.isAlertDismissed;
+    },
+  },
+  methods: {
+    reportError(error) {
+      this.errorMessage = error;
+      this.isAlertDismissed = false;
+    },
+    async toggleCVS(checked) {
+      try {
+        const { data } = await this.$apollo.mutate({
+          mutation: ProjectSetContinuousVulnerabilityScanning,
+          variables: {
+            input: {
+              projectPath: this.projectFullPath,
+              enable: checked,
+            },
+          },
+        });
+
+        const { errors } = data.projectSetContinuousVulnerabilityScanning;
+
+        if (errors.length > 0) {
+          this.reportError(errors[0].message);
+        }
+        if (data.projectSetContinuousVulnerabilityScanning !== null) {
+          this.toggleValue = checked;
+        }
+      } catch (error) {
+        this.reportError(error);
+      }
+    },
+  },
+  CVSHelpPagePath: helpPagePath(
+    'user/application_security/continuous_vulnerability_scanning/index',
+  ),
+  experimentHelpPagePath: helpPagePath('policy/experiment-beta-support', { anchor: 'experiment' }),
+};
+</script>
+
+<template>
+  <div v-if="glFeatures.dependencyScanningOnAdvisoryIngestion">
+    <h4 class="gl-font-base gl-m-0 gl-mt-6">
+      {{ $options.i18n.title }}
+      <gl-badge
+        ref="badge"
+        :href="$options.experimentHelpPagePath"
+        target="_blank"
+        size="sm"
+        variant="neutral"
+        class="gl-cursor-pointer"
+        >{{ $options.i18n.badgeLabel }}</gl-badge
+      >
+    </h4>
+    <gl-alert
+      v-if="shouldShowAlert"
+      class="gl-mb-5 gl-mt-2"
+      variant="danger"
+      @dismiss="isAlertDismissed = true"
+      >{{ errorMessage }}</gl-alert
+    >
+    <gl-toggle
+      class="gl-mt-5"
+      :disabled="!isFeatureConfigured"
+      :value="toggleValue"
+      :label="s__('CVS|Toggle CVS')"
+      label-position="hidden"
+      @change="toggleCVS"
+    />
+
+    <p class="gl-mb-0 gl-mt-5">
+      {{ $options.i18n.description }}
+      <gl-link :href="$options.CVSHelpPagePath" target="_blank">{{
+        $options.i18n.learnMore
+      }}</gl-link>
+      <br />
+      <gl-sprintf :message="$options.i18n.testingAgreementMessage">
+        <template #link="{ content }">
+          <gl-link href="https://about.gitlab.com/handbook/legal/testing-agreement" target="_blank">
+            {{ content }} <gl-icon name="external-link" />
+          </gl-link>
+        </template>
+      </gl-sprintf>
+    </p>
+  </div>
+</template>
diff --git a/app/assets/javascripts/security_configuration/components/feature_card.vue b/app/assets/javascripts/security_configuration/components/feature_card.vue
index a757657339b6ee89a84073c83e1a0a3a3e9ac91c..7f0a049a6adcd3dd85560571896846faa149542b 100644
--- a/app/assets/javascripts/security_configuration/components/feature_card.vue
+++ b/app/assets/javascripts/security_configuration/components/feature_card.vue
@@ -73,6 +73,9 @@ export default {
     hasSecondary() {
       return Boolean(this.feature.secondary);
     },
+    hasSlotComponent() {
+      return Boolean(this.feature.slotComponent);
+    },
     // This condition is a temporary hack to not display any wrong information
     // until this BE Bug is fixed: https://gitlab.com/gitlab-org/gitlab/-/issues/350307.
     // More Information: https://gitlab.com/gitlab-org/gitlab/-/issues/350307#note_825447417
@@ -215,5 +218,9 @@ export default {
         {{ $options.i18n.configurationGuide }}
       </gl-button>
     </div>
+
+    <div v-if="hasSlotComponent">
+      <component :is="feature.slotComponent" :feature="feature" />
+    </div>
   </gl-card>
 </template>
diff --git a/ee/app/assets/javascripts/security_configuration/graphql/project_set_continuous_vulnerability_scanning.graphql b/app/assets/javascripts/security_configuration/graphql/project_set_continuous_vulnerability_scanning.graphql
similarity index 100%
rename from ee/app/assets/javascripts/security_configuration/graphql/project_set_continuous_vulnerability_scanning.graphql
rename to app/assets/javascripts/security_configuration/graphql/project_set_continuous_vulnerability_scanning.graphql
diff --git a/app/assets/javascripts/security_configuration/index.js b/app/assets/javascripts/security_configuration/index.js
index aa3c9c876221d46d0253ad46378c2716428fdac6..4b4980911342cca896fdb371c7d9c47295bbebcb 100644
--- a/app/assets/javascripts/security_configuration/index.js
+++ b/app/assets/javascripts/security_configuration/index.js
@@ -26,6 +26,7 @@ export const initSecurityConfiguration = (el) => {
     autoDevopsHelpPagePath,
     autoDevopsPath,
     vulnerabilityTrainingDocsPath,
+    continuousVulnerabilityScansEnabled,
   } = el.dataset;
 
   const { augmentedSecurityFeatures } = augmentFeatures(
@@ -43,6 +44,7 @@ export const initSecurityConfiguration = (el) => {
       autoDevopsHelpPagePath,
       autoDevopsPath,
       vulnerabilityTrainingDocsPath,
+      continuousVulnerabilityScansEnabled,
     },
     render(createElement) {
       return createElement(SecurityConfigurationApp, {
diff --git a/ee/app/controllers/ee/projects/security/configuration_controller.rb b/ee/app/controllers/ee/projects/security/configuration_controller.rb
index e8e1d556ef961a2f5e31fa78082b001c8642632c..e3988390624fb27bf1181d2643782828c6305955 100644
--- a/ee/app/controllers/ee/projects/security/configuration_controller.rb
+++ b/ee/app/controllers/ee/projects/security/configuration_controller.rb
@@ -14,6 +14,7 @@ module ConfigurationController
 
           before_action only: [:show] do
             push_frontend_feature_flag(:security_auto_fix, project)
+            push_frontend_feature_flag(:dependency_scanning_on_advisory_ingestion, project)
           end
 
           before_action only: [:auto_fix] do
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 681e93ed8dade46662f722da476c11140c63e101..912ecb353bc5591a3f5eb262ed361d237fe1895d 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -9172,6 +9172,18 @@ msgstr ""
 msgid "CVE|Why Request a CVE ID?"
 msgstr ""
 
+msgid "CVS|By enabling this feature, you accept the %{linkStart}Testing Terms of Use%{linkEnd}"
+msgstr ""
+
+msgid "CVS|Continuous Vulnerability Scan"
+msgstr ""
+
+msgid "CVS|Detect vulnerabilities outside a pipeline as new data is added to the GitLab Advisory Database."
+msgstr ""
+
+msgid "CVS|Toggle CVS"
+msgstr ""
+
 msgid "Cadence is not automated"
 msgstr ""
 
diff --git a/spec/frontend/security_configuration/components/continuous_vulnerability_scan_spec.js b/spec/frontend/security_configuration/components/continuous_vulnerability_scan_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..84a468e4dd832cf1a554a4b1ece310f1205e9c88
--- /dev/null
+++ b/spec/frontend/security_configuration/components/continuous_vulnerability_scan_spec.js
@@ -0,0 +1,124 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlBadge, GlToggle } from '@gitlab/ui';
+import VueApollo from 'vue-apollo';
+import Vue from 'vue';
+import ProjectSetContinuousVulnerabilityScanning from '~/security_configuration/graphql/project_set_continuous_vulnerability_scanning.graphql';
+import ContinuousVulnerabilityScan from '~/security_configuration/components/continuous_vulnerability_scan.vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
+
+Vue.use(VueApollo);
+
+const setCVSMockResponse = {
+  data: {
+    projectSetContinuousVulnerabilityScanning: {
+      continuousVulnerabilityScanningEnabled: true,
+      errors: [],
+    },
+  },
+};
+
+const defaultProvide = {
+  continuousVulnerabilityScansEnabled: true,
+  projectFullPath: 'project/full/path',
+};
+
+describe('ContinuousVulnerabilityScan', () => {
+  let wrapper;
+  let apolloProvider;
+  let requestHandlers;
+
+  const createComponent = (options) => {
+    requestHandlers = {
+      setCVSMutationHandler: jest.fn().mockResolvedValue(setCVSMockResponse),
+    };
+
+    apolloProvider = createMockApollo([
+      [ProjectSetContinuousVulnerabilityScanning, requestHandlers.setCVSMutationHandler],
+    ]);
+
+    wrapper = shallowMount(ContinuousVulnerabilityScan, {
+      propsData: {
+        feature: {
+          available: true,
+          configured: true,
+        },
+      },
+      provide: {
+        glFeatures: {
+          dependencyScanningOnAdvisoryIngestion: true,
+        },
+        ...defaultProvide,
+      },
+      apolloProvider,
+      ...options,
+    });
+  };
+
+  beforeEach(() => {
+    createComponent();
+  });
+
+  afterEach(() => {
+    apolloProvider = null;
+  });
+
+  const findBadge = () => wrapper.findComponent(GlBadge);
+  const findToggle = () => wrapper.findComponent(GlToggle);
+
+  it('renders the component', () => {
+    expect(wrapper.exists()).toBe(true);
+  });
+
+  it('renders the correct title', () => {
+    expect(wrapper.text()).toContain('Continuous Vulnerability Scan');
+  });
+
+  it('renders the badge and toggle component with correct values', () => {
+    expect(findBadge().exists()).toBe(true);
+    expect(findBadge().text()).toBe('Experiment');
+
+    expect(findToggle().exists()).toBe(true);
+    expect(findToggle().props('value')).toBe(defaultProvide.continuousVulnerabilityScansEnabled);
+  });
+
+  it('should disable toggle when feature is not configured', () => {
+    createComponent({
+      propsData: {
+        feature: {
+          available: true,
+          configured: false,
+        },
+      },
+    });
+    expect(findToggle().props('disabled')).toBe(true);
+  });
+
+  it('calls mutation on toggle change with correct payload', () => {
+    findToggle().vm.$emit('change', true);
+
+    expect(requestHandlers.setCVSMutationHandler).toHaveBeenCalledWith({
+      input: {
+        projectPath: 'project/full/path',
+        enable: true,
+      },
+    });
+  });
+
+  describe('when feature flag is disabled', () => {
+    beforeEach(() => {
+      createComponent({
+        provide: {
+          glFeatures: {
+            dependencyScanningOnAdvisoryIngestion: false,
+          },
+          ...defaultProvide,
+        },
+      });
+    });
+
+    it('should not render toggle and badge', () => {
+      expect(findToggle().exists()).toBe(false);
+      expect(findBadge().exists()).toBe(false);
+    });
+  });
+});
diff --git a/spec/frontend/security_configuration/components/feature_card_spec.js b/spec/frontend/security_configuration/components/feature_card_spec.js
index 983a66a7fd3dfdb9b127269ce502b13710385435..c715d01dd581e9f2be26ac2de4e19d98680f92d3 100644
--- a/spec/frontend/security_configuration/components/feature_card_spec.js
+++ b/spec/frontend/security_configuration/components/feature_card_spec.js
@@ -1,5 +1,6 @@
 import { GlIcon } from '@gitlab/ui';
 import { mount } from '@vue/test-utils';
+import Vue from 'vue';
 import { extendedWrapper } from 'helpers/vue_test_utils_helper';
 import { securityFeatures } from '~/security_configuration/components/constants';
 import FeatureCard from '~/security_configuration/components/feature_card.vue';
@@ -13,6 +14,10 @@ import {
 import { manageViaMRErrorMessage } from '../constants';
 import { makeFeature } from './utils';
 
+const MockComponent = Vue.component('MockComponent', {
+  render: (createElement) => createElement('span'),
+});
+
 describe('FeatureCard component', () => {
   let feature;
   let wrapper;
@@ -389,4 +394,17 @@ describe('FeatureCard component', () => {
       });
     });
   });
+
+  describe('when a slot component is passed', () => {
+    beforeEach(() => {
+      feature = makeFeature({
+        slotComponent: MockComponent,
+      });
+      createComponent({ feature });
+    });
+
+    it('renders the component properly', () => {
+      expect(wrapper.findComponent(MockComponent).exists()).toBe(true);
+    });
+  });
 });