diff --git a/ee/app/finders/sbom/possibly_affected_occurrences_finder.rb b/ee/app/finders/sbom/possibly_affected_occurrences_finder.rb
index ed84f649c978bf085b5f85a85bfe30299427c76c..37d41e6c1bd723e852bd841818b6a1a9bb1008c1 100644
--- a/ee/app/finders/sbom/possibly_affected_occurrences_finder.rb
+++ b/ee/app/finders/sbom/possibly_affected_occurrences_finder.rb
@@ -21,6 +21,7 @@ def execute_in_batches(of: BATCH_SIZE)
       search_scope.each_batch(of: of) do |batch|
         yield batch
           .with_component_source_version_and_project
+          .with_project_setting
           .with_pipeline_project_and_namespace
           .filter_by_non_nil_component_version
       end
diff --git a/ee/app/models/sbom/occurrence.rb b/ee/app/models/sbom/occurrence.rb
index 28a9d0a47ad4b0dc1a54041072d7cd26cab5bc07..596f8e9ff26d321e6f2b67f01891ddf190356da4 100644
--- a/ee/app/models/sbom/occurrence.rb
+++ b/ee/app/models/sbom/occurrence.rb
@@ -167,6 +167,7 @@ class Occurrence < ApplicationRecord
       includes(:component, :source, :component_version, :project)
       .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/473758')
     end
+    scope :with_project_setting, -> { preload(project: :project_setting) }
     scope :filter_by_non_nil_component_version, -> { where.not(component_version: nil) }
 
     scope :order_by_severity, ->(direction) do
diff --git a/ee/app/services/security/ingestion/ingest_cvs_slice_service.rb b/ee/app/services/security/ingestion/ingest_cvs_slice_service.rb
index a96f4074189db58f0f5202f9bb4fb82dedbe62ae..4b62e22bce04fd3196b8548a65bf807f1839a93c 100644
--- a/ee/app/services/security/ingestion/ingest_cvs_slice_service.rb
+++ b/ee/app/services/security/ingestion/ingest_cvs_slice_service.rb
@@ -16,6 +16,7 @@ class IngestCvsSliceService < IngestSliceBaseService
         IngestFindingEvidence
         IngestVulnerabilityFlags
         IngestVulnerabilityReads
+        MarkCvsProjectsAsVulnerable
         IngestVulnerabilityStatistics
         HooksExecution
       ].freeze
diff --git a/ee/app/services/security/ingestion/tasks/mark_cvs_projects_as_vulnerable.rb b/ee/app/services/security/ingestion/tasks/mark_cvs_projects_as_vulnerable.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1efd72511b3437250c4b1033d0cd192848be804b
--- /dev/null
+++ b/ee/app/services/security/ingestion/tasks/mark_cvs_projects_as_vulnerable.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Security
+  module Ingestion
+    module Tasks
+      class MarkCvsProjectsAsVulnerable < AbstractTask
+        def execute
+          new_vulnerable_projects.each(&:mark_as_vulnerable!)
+        end
+
+        private
+
+        def new_vulnerable_projects
+          unique_projects.select { |project| !project.project_setting&.has_vulnerabilities? }
+        end
+
+        def unique_projects
+          finding_maps.map(&:project).uniq
+        end
+      end
+    end
+  end
+end
diff --git a/ee/spec/models/sbom/occurrence_spec.rb b/ee/spec/models/sbom/occurrence_spec.rb
index 682c79101f5d754e088d532f2d5f0e9cb37cbae5..fe668e99713bb817d9106db7f094bbd6bef5476e 100644
--- a/ee/spec/models/sbom/occurrence_spec.rb
+++ b/ee/spec/models/sbom/occurrence_spec.rb
@@ -151,6 +151,21 @@
     end
   end
 
+  describe '.with_project_setting' do
+    let!(:occurrence) { create(:sbom_occurrence) }
+
+    it 'pre-loads relations to avoid executing additional queries' do
+      record = described_class.with_project_setting.first
+
+      queries = ActiveRecord::QueryRecorder.new do
+        record.project
+        record.project.project_setting
+      end
+
+      expect(queries.count).to be_zero
+    end
+  end
+
   describe '.with_pipeline_project_and_namespace' do
     before do
       create(:sbom_occurrence, component: create(:sbom_component))
diff --git a/ee/spec/services/security/ingestion/tasks/mark_cvs_projects_as_vulnerable_spec.rb b/ee/spec/services/security/ingestion/tasks/mark_cvs_projects_as_vulnerable_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..9d11b5df2c0c0fbffd6682033cbb335e85ef9acb
--- /dev/null
+++ b/ee/spec/services/security/ingestion/tasks/mark_cvs_projects_as_vulnerable_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Security::Ingestion::Tasks::MarkCvsProjectsAsVulnerable, feature_category: :software_composition_analysis do
+  describe '#execute' do
+    let(:project_setting_1) { create(:project_setting, has_vulnerabilities: false) }
+    let(:project_setting_2) { create(:project_setting, has_vulnerabilities: true) }
+
+    let(:project_1) { project_setting_1.project }
+    let(:project_2) { project_setting_2.project }
+    let(:project_3) { create(:project) }
+
+    let(:pipeline_1) { create(:ci_pipeline, project: project_1) }
+    let(:pipeline_2) { create(:ci_pipeline, project: project_2) }
+    let(:pipeline_3) { create(:ci_pipeline, project: project_3) }
+
+    let(:finding_map_1) { create(:vs_finding_map, pipeline: pipeline_1) }
+    let(:finding_map_2) { create(:vs_finding_map, pipeline: pipeline_2) }
+    let(:finding_map_3) { create(:vs_finding_map, pipeline: pipeline_3) }
+
+    let(:task) { described_class.new(nil, [finding_map_1, finding_map_2, finding_map_3]) }
+
+    subject(:execute) { task.execute }
+
+    it 'marks projects as has_vulnerabilities' do
+      expect { execute }.to change { project_1.reload.project_setting.has_vulnerabilities? }.to(true)
+                        .and change { project_3.reload.project_setting.has_vulnerabilities? }.to(true)
+                        .and not_change { project_2.reload.project_setting.has_vulnerabilities? }.from(true)
+    end
+  end
+end