diff options
| author | GeogeFI | 2022-04-02 20:16:46 +0200 |
|---|---|---|
| committer | GeogeFI | 2022-04-02 20:16:46 +0200 |
| commit | 9eed55b6104fd7acf5879035729d422ecca79e19 (patch) | |
| tree | 9429025cbbe8fec0f35bb59d9804996ab355a0f3 | |
| parent | 7aef566f501eeb5909549d05ecb1e82b9162cf95 (diff) | |
| download | sec-certs-9eed55b6104fd7acf5879035729d422ecca79e19.tar.gz sec-certs-9eed55b6104fd7acf5879035729d422ecca79e19.tar.zst sec-certs-9eed55b6104fd7acf5879035729d422ecca79e19.zip | |
feat: Partly implemented module, not integrated with dataset, nor tested
| -rw-r--r-- | sec_certs/model/dependency_vulnerability_finder.py | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/sec_certs/model/dependency_vulnerability_finder.py b/sec_certs/model/dependency_vulnerability_finder.py new file mode 100644 index 00000000..4ea9130b --- /dev/null +++ b/sec_certs/model/dependency_vulnerability_finder.py @@ -0,0 +1,96 @@ +import logging +from dataclasses import dataclass, field +from enum import Enum +from typing import Dict, Optional, Set + +from sec_certs.sample.certificate import Certificate +from sec_certs.serialization.json import ComplexSerializableType + + +class DependencyType(Enum): + DIRECT = "direct" + INDIRECT = "indirect" + + +@dataclass +class DependencyCVE(ComplexSerializableType): + direct_dependency_cves: Optional[Set[str]] = field(default=None) + indirect_dependency_cves: Optional[Set[str]] = field(default=None) + + +Certificates = Dict[str, Certificate] +Vulnerabilities = Dict[str, Optional[Set[str]]] + + +class DependencyVulnerabilityFinder: + def __init__(self, certificates: Certificates): + self.vulnerabilities: Vulnerabilities = {} + self.certificates = certificates + + def _get_dataset_cert_ids(self) -> Dict[str, int]: + cert_id_occurrences: Dict[str, int] = {} + + for dgst in self.certificates: + cert_id = self.certificates[dgst].heuristics.cert_id + + if cert_id is None: + continue + + cert_id_occurrences[cert_id] = cert_id_occurrences.get(cert_id, 0) + 1 + + return cert_id_occurrences + + def _get_dependency_cves(self, dgst: str, dependency_type: DependencyType) -> Optional[Set[str]]: + dependency_type_dict = { + DependencyType.DIRECT: self.certificates[dgst].heuristics.report_references.directly_referenced_by, + DependencyType.INDIRECT: self.certificates[dgst].heuristics.report_references.indirectly_referenced_by, + } + + references = dependency_type_dict[dependency_type] + + if not references: + return None + + vulnerabilities = set() + dataset_cert_id_occurrences = self._get_dataset_cert_ids() + + for cert_id in references: + cert_id_occurrences = dataset_cert_id_occurrences.get(cert_id, None) + + if cert_id is None or cert_id_occurrences[cert_id] >= 2: + continue + + for dgst in self.certificates: + cert_obj = self.certificates[dgst] + + if cert_obj.heuristics.cert_id == cert_id and cert_obj.heuristics.related_cves: + vulnerabilities.update(cert_obj.heuristics.related_cves) + + return vulnerabilities if vulnerabilities else None + + def fit(self) -> Vulnerabilities: + cert_id_occurrences = self._get_dataset_cert_ids() + thrown_away_counter = 0 + + for dgst in self.certificates: + cert_id = self.certificates[dgst].heuristics.cert_id + + if cert_id is None or cert_id_occurrences[cert_id] >= 2: + thrown_away_counter += 1 + continue + + self.vulnerabilities[dgst][DependencyType.DIRECT] = self._get_dependency_cves(dgst, DependencyType.DIRECT) + self.vulnerabilities[dgst][DependencyType.INDIRECT] = self._get_dependency_cves( + dgst, DependencyType.INDIRECT + ) + + if thrown_away_counter > 0: + logging.warning("There were total of %s certificates skipped due to duplicity", thrown_away_counter) + + return self.vulnerabilities + + def get_dependency_vulnerabilities(self, dgst: str) -> DependencyCVE: + return DependencyCVE( + self.vulnerabilities[dgst][DependencyType.DIRECT], + self.vulnerabilities[dgst][DependencyType.INDIRECT], + ) |
