36
36
from typing import Tuple
37
37
38
38
from binaryornot .helpers import is_binary_string
39
+ from dateutil import parser as dateparser
39
40
from git import DiffIndex
40
41
from git import Repo
41
42
from license_expression import Licensing
42
43
from packageurl import PackageURL
44
+ from univers .version_range import RANGE_CLASS_BY_SCHEMES
43
45
from univers .version_range import VersionRange
44
46
from univers .versions import Version
45
47
46
48
from vulnerabilities .helpers import classproperty
47
49
from vulnerabilities .helpers import evolve_purl
48
- from vulnerabilities .helpers import nearest_patched_package
49
50
from vulnerabilities .oval_parser import OvalParser
50
51
from vulnerabilities .severity_systems import SCORING_SYSTEMS
51
52
from vulnerabilities .severity_systems import ScoringSystem
@@ -510,13 +511,13 @@ class OvalImporter(Importer):
510
511
"""
511
512
512
513
@staticmethod
513
- def create_purl (pkg_name : str , pkg_version : str , pkg_data : Mapping ) -> PackageURL :
514
+ def create_purl (pkg_name : str , pkg_data : Mapping ) -> PackageURL :
514
515
"""
515
516
Helper method for creating different purls for subclasses without them reimplementing
516
517
get_data_from_xml_doc method
517
518
Note: pkg_data must include 'type' of package
518
519
"""
519
- return PackageURL (name = pkg_name , version = pkg_version , ** pkg_data )
520
+ return PackageURL (name = pkg_name , ** pkg_data )
520
521
521
522
@staticmethod
522
523
def _collect_pkgs (parsed_oval_data : Mapping ) -> Set :
@@ -550,28 +551,17 @@ def advisory_data(self) -> List[AdvisoryData]:
550
551
for metadata , oval_file in self ._fetch ():
551
552
try :
552
553
oval_data = self .get_data_from_xml_doc (oval_file , metadata )
553
- yield oval_data
554
+ yield from oval_data
554
555
except Exception :
555
556
logger .error (
556
557
f"Failed to get updated_advisories: { oval_file !r} "
557
558
f"with { metadata !r} :\n " + traceback .format_exc ()
558
559
)
559
560
continue
560
561
561
- def set_api (self , all_pkgs : Iterable [str ]):
562
- """
563
- This method loads the self.pkg_manager_api with the specified packages.
564
- It fetches and caches all the versions of these packages and exposes
565
- them through self.pkg_manager_api.get(<package_name>). Example
566
-
567
- >> self.set_api(['electron'])
568
- Assume 'electron' has only versions 1.0.0 and 1.2.0
569
- >> assert self.pkg_manager_api.get('electron') == {'1.0.0','1.2.0'}
570
-
571
- """
572
- raise NotImplementedError
573
-
574
- def get_data_from_xml_doc (self , xml_doc : ET .ElementTree , pkg_metadata = {}) -> List [AdvisoryData ]:
562
+ def get_data_from_xml_doc (
563
+ self , xml_doc : ET .ElementTree , pkg_metadata = {}
564
+ ) -> Iterable [AdvisoryData ]:
575
565
"""
576
566
The orchestration method of the OvalDataSource. This method breaks an
577
567
OVAL xml ElementTree into a list of `Advisory`.
@@ -584,10 +574,11 @@ def get_data_from_xml_doc(self, xml_doc: ET.ElementTree, pkg_metadata={}) -> Lis
584
574
"""
585
575
586
576
all_adv = []
587
- oval_doc = OvalParser (self .translations , xml_doc )
588
- raw_data = oval_doc .get_data ()
589
- all_pkgs = self ._collect_pkgs (raw_data )
590
- self .set_api (all_pkgs )
577
+ oval_parsed_data = OvalParser (self .translations , xml_doc )
578
+ raw_data = oval_parsed_data .get_data ()
579
+ oval_doc = oval_parsed_data .oval_document
580
+ timestamp = oval_doc .getGenerator ().getTimestamp ()
581
+ # all_pkgs = self._collect_pkgs(raw_data)
591
582
592
583
# convert definition_data to Advisory objects
593
584
for definition_data in raw_data :
@@ -599,49 +590,28 @@ def get_data_from_xml_doc(self, xml_doc: ET.ElementTree, pkg_metadata={}) -> Lis
599
590
affected_packages = []
600
591
for test_data in definition_data ["test_data" ]:
601
592
for package_name in test_data ["package_list" ]:
602
- if package_name and len (package_name ) >= 50 :
603
- continue
604
-
605
- affected_version_range = test_data ["version_ranges" ] or set ()
606
- version_class = version_class_by_package_type [pkg_metadata ["type" ]]
607
- version_scheme = version_class .scheme
608
-
609
- affected_version_range = VersionRange .from_scheme_version_spec_string (
610
- version_scheme , affected_version_range
611
- )
612
- all_versions = self .pkg_manager_api .get (package_name ).valid_versions
613
-
614
- # FIXME: what is this 50 DB limit? that's too small for versions
615
- # FIXME: we should not drop data this way
616
- # This filter is for filtering out long versions.
617
- # 50 is limit because that's what db permits atm.
618
- all_versions = [version for version in all_versions if len (version ) < 50 ]
619
- if not all_versions :
620
- continue
621
-
622
- affected_purls = []
623
- safe_purls = []
624
- for version in all_versions :
625
- purl = self .create_purl (
626
- pkg_name = package_name ,
627
- pkg_version = version ,
628
- pkg_data = pkg_metadata ,
593
+ affected_version_range = test_data ["version_ranges" ]
594
+ vrc = RANGE_CLASS_BY_SCHEMES [pkg_metadata ["type" ]]
595
+ if affected_version_range :
596
+ try :
597
+ affected_version_range = vrc .from_native (affected_version_range )
598
+ except Exception as e :
599
+ logger .error (
600
+ f"Failed to parse version range { affected_version_range !r} "
601
+ f"for package { package_name !r} :\n { e } "
602
+ )
603
+ continue
604
+ if package_name :
605
+ affected_packages .append (
606
+ AffectedPackage (
607
+ package = self .create_purl (package_name , pkg_metadata ),
608
+ affected_version_range = affected_version_range ,
609
+ )
629
610
)
630
- if version_class (version ) in affected_version_range :
631
- affected_purls .append (purl )
632
- else :
633
- safe_purls .append (purl )
634
-
635
- affected_packages .extend (
636
- nearest_patched_package (affected_purls , safe_purls ),
637
- )
638
-
639
- all_adv .append (
640
- AdvisoryData (
641
- summary = description ,
642
- affected_packages = affected_packages ,
643
- vulnerability_id = vuln_id ,
644
- references = references ,
645
- )
611
+ yield AdvisoryData (
612
+ aliases = [vuln_id ],
613
+ summary = description ,
614
+ affected_packages = affected_packages ,
615
+ references = references ,
616
+ date_published = dateparser .parse (timestamp ),
646
617
)
647
- return all_adv
0 commit comments