From fbb3f86c70b4df1f8275563b04913ea29ce69585 Mon Sep 17 00:00:00 2001 From: Yasha Rise <yrise@gitlab.com> Date: Tue, 31 Dec 2024 14:59:18 +0000 Subject: [PATCH] Populate cve column in pm_advisories at ingestion --- .../package_metadata/advisory_data_object.rb | 15 +++++- .../advisory/advisory_ingestion_task.rb | 1 + .../package_metadata/advisory_data_objects.rb | 1 + .../advisory_data_object_spec.rb | 46 ++++++++++++++++++- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/ee/app/services/package_metadata/advisory_data_object.rb b/ee/app/services/package_metadata/advisory_data_object.rb index 9d8b0bb0668b6..5c270e5a438d4 100644 --- a/ee/app/services/package_metadata/advisory_data_object.rb +++ b/ee/app/services/package_metadata/advisory_data_object.rb @@ -12,6 +12,7 @@ def self.create(data, purl_type) end advisory['source_xid'] = source + advisory['cve'] = extract_cve(advisory['identifiers']) packages = data['packages'].clone raise ArgumentError, 'Missing packages attribute' unless packages @@ -26,13 +27,22 @@ def self.create_affected_packages(packages, purl_type) end end + def self.extract_cve(identifiers) + return unless identifiers + + cve_identifier = identifiers.find { |identifier| identifier['type']&.casecmp?('cve') } + cve_identifier['name'] if cve_identifier + end + + private_class_method :extract_cve + attr_accessor :advisory_xid, :source_xid, :published_date, :title, :description, :cvss_v2, :cvss_v3, :urls, - :identifiers, :affected_packages + :identifiers, :affected_packages, :cve # rubocop:disable Metrics/ParameterLists def initialize( advisory_xid:, source_xid:, published_date:, title: '', description: '', cvss_v2: nil, cvss_v3: nil, urls: [], - identifiers: [], affected_packages: []) + identifiers: [], affected_packages: [], cve: nil) # rubocop:enable Metrics/ParameterLists @advisory_xid = advisory_xid @source_xid = source_xid @@ -44,6 +54,7 @@ def initialize( @urls = urls @identifiers = identifiers.map { |ident| ident.transform_keys(&:to_sym) } @affected_packages = affected_packages + @cve = cve end end end diff --git a/ee/app/services/package_metadata/ingestion/advisory/advisory_ingestion_task.rb b/ee/app/services/package_metadata/ingestion/advisory/advisory_ingestion_task.rb index 33111ba7dfeb7..180e2e5fe6305 100644 --- a/ee/app/services/package_metadata/ingestion/advisory/advisory_ingestion_task.rb +++ b/ee/app/services/package_metadata/ingestion/advisory/advisory_ingestion_task.rb @@ -66,6 +66,7 @@ def advisories cvss_v3: data_object.cvss_v3, identifiers: data_object.identifiers, urls: data_object.urls, + cve: data_object.cve, created_at: now, updated_at: now ) diff --git a/ee/spec/factories/package_metadata/advisory_data_objects.rb b/ee/spec/factories/package_metadata/advisory_data_objects.rb index 91506f88987c6..6e3a93f44e131 100644 --- a/ee/spec/factories/package_metadata/advisory_data_objects.rb +++ b/ee/spec/factories/package_metadata/advisory_data_objects.rb @@ -16,6 +16,7 @@ association(:pm_identifier, :gemnasium) ] end + cve { identifiers[0]['name'] } affected_packages { [association(:pm_affected_package_data_object)] } diff --git a/ee/spec/services/package_metadata/advisory_data_object_spec.rb b/ee/spec/services/package_metadata/advisory_data_object_spec.rb index dd2c56ec5df3c..895549da5676a 100644 --- a/ee/spec/services/package_metadata/advisory_data_object_spec.rb +++ b/ee/spec/services/package_metadata/advisory_data_object_spec.rb @@ -71,7 +71,8 @@ have_attributes(purl_type: purl_type, package_name: 'org.jenkins-ci.plugins/google-kubernetes-engine', affected_range: '(,0.7.0]', solution: 'Upgrade to version 0.8 or above.', fixed_versions: ["0.8"]) - ])) + ], + cve: "CVE-2019-10445")) } context 'when an attribute is missing' do @@ -90,6 +91,7 @@ :cvvs_v3 | false :urls | false :identifiers | false + :cve | false :id | true :source | true end @@ -132,5 +134,47 @@ end end end + + context 'when there is no CVE identifier' do + let(:hash) do + { + "advisory" => + { + "id" => "test-id", + "source" => "glad", + "published_date" => "2023-01-01", + "identifiers" => [ + { "type" => "cwe", "name" => "CWE-79", "value" => "79" } + ] + }, + "packages" => [] + } + end + + it 'sets cve to nil' do + expect(described_class.create(hash, purl_type).cve).to be_nil + end + end + + context 'when the CVE type is in different case' do + let(:hash) do + { + "advisory" => + { + "id" => "test-id", + "source" => "glad", + "published_date" => "2023-01-01", + "identifiers" => [ + { "type" => "CVe", "name" => "CVE-2021-5678", "value" => "CVE-2021-5678" } + ] + }, + "packages" => [] + } + end + + it 'extracts the CVE name case-insensitively' do + expect(described_class.create(hash, purl_type).cve).to eq('CVE-2021-5678') + end + end end end -- GitLab