diff --git a/vulnerabilities/importer.py b/vulnerabilities/importer.py index 850587ca7..cd32dcdce 100644 --- a/vulnerabilities/importer.py +++ b/vulnerabilities/importer.py @@ -37,8 +37,8 @@ from vulnerabilities.severity_systems import ScoringSystem from vulnerabilities.utils import classproperty from vulnerabilities.utils import get_reference_id +from vulnerabilities.utils import is_commit from vulnerabilities.utils import is_cve -from vulnerabilities.utils import nearest_patched_package from vulnerabilities.utils import purl_to_dict from vulnerabilities.utils import update_purl_version @@ -194,6 +194,64 @@ def from_url(cls, url): return cls(url=url) +@dataclasses.dataclass(eq=True) +@functools.total_ordering +class CodeCommitData: + commit_hash: str + vcs_url: str + + commit_author: Optional[str] = None + commit_message: Optional[str] = None + commit_date: Optional[datetime.datetime] = None + + def __post_init__(self): + if not self.commit_hash: + raise ValueError("Commit must have a non-empty commit_hash.") + + if not is_commit(self.commit_hash): + raise ValueError("Commit must be a valid a commit_hash.") + + if not self.vcs_url: + raise ValueError("Commit must have a non-empty vcs_url.") + + def __lt__(self, other): + if not isinstance(other, CodeCommitData): + return NotImplemented + return self._cmp_key() < other._cmp_key() + + # TODO: Add cache + def _cmp_key(self): + return ( + self.commit_hash, + self.vcs_url, + self.commit_author, + self.commit_message, + self.commit_date, + ) + + def to_dict(self) -> dict: + """Return a normalized dictionary representation of the commit.""" + return { + "commit_hash": self.commit_hash, + "vcs_url": self.vcs_url, + "commit_author": self.commit_author, + "commit_message": self.commit_message, + "commit_date": self.commit_date, + } + + @classmethod + def from_dict(cls, data: dict): + """Create a Commit instance from a dictionary.""" + commit_date = data.get("commit_date") + return cls( + commit_hash=str(data.get("commit_hash", "")), + vcs_url=data.get("vcs_url", ""), + commit_author=data.get("commit_author"), + commit_message=data.get("commit_message"), + commit_date=datetime.datetime.fromisoformat(commit_date) if commit_date else None, + ) + + class UnMergeablePackageError(Exception): """ Raised when a package cannot be merged with another one. @@ -344,18 +402,25 @@ class AffectedPackageV2: """ Relate a Package URL with a range of affected versions and fixed versions. The Package URL must *not* have a version. - AffectedPackage must contain either ``affected_version_range`` or ``fixed_version_range``. + AffectedPackage must contain either ``affected_version_range`` or ``fixed_version_range`` or ``affected_by_commits`` or ``fixed_by_commits``. """ package: PackageURL affected_version_range: Optional[VersionRange] = None fixed_version_range: Optional[VersionRange] = None + fixed_by_commits: List[CodeCommitData] = dataclasses.field(default_factory=list) + affected_by_commits: List[CodeCommitData] = dataclasses.field(default_factory=list) def __post_init__(self): if self.package.version: raise ValueError(f"Affected Package URL {self.package!r} cannot have a version.") - if not (self.affected_version_range or self.fixed_version_range): + if not ( + self.affected_version_range + or self.fixed_version_range + or self.affected_by_commits + or self.fixed_by_commits + ): raise ValueError( f"Affected Package {self.package!r} should have either fixed version range or an " "affected version range." @@ -372,6 +437,8 @@ def _cmp_key(self): str(self.package), str(self.affected_version_range or ""), str(self.fixed_version_range or ""), + str(self.affected_by_commits or []), + str(self.fixed_by_commits or []), ) def to_dict(self): @@ -385,6 +452,12 @@ def to_dict(self): "package": purl_to_dict(self.package), "affected_version_range": affected_version_range, "fixed_version_range": fixed_version_range, + "affected_by_commits": [ + affected_by_commit.to_dict() for affected_by_commit in self.affected_by_commits + ], + "fixed_by_commits": [ + fixed_by_commit.to_dict() for fixed_by_commit in self.fixed_by_commits + ], } @classmethod @@ -396,6 +469,8 @@ def from_dict(cls, affected_pkg: dict): fixed_version_range = None affected_range = affected_pkg["affected_version_range"] fixed_range = affected_pkg["fixed_version_range"] + affected_by_commits = affected_pkg.get("affected_by_commits") or [] + fixed_by_commits = affected_pkg.get("fixed_by_commits") or [] try: affected_version_range = VersionRange.from_string(affected_range) @@ -417,6 +492,13 @@ def from_dict(cls, affected_pkg: dict): package=package, affected_version_range=affected_version_range, fixed_version_range=fixed_version_range, + affected_by_commits=[ + CodeCommitData.from_dict(affected_by_commit) + for affected_by_commit in affected_by_commits + ], + fixed_by_commits=[ + CodeCommitData.from_dict(fixed_by_commit) for fixed_by_commit in fixed_by_commits + ], ) diff --git a/vulnerabilities/importers/osv.py b/vulnerabilities/importers/osv.py index 8bd4ad274..b8ecd0d9d 100644 --- a/vulnerabilities/importers/osv.py +++ b/vulnerabilities/importers/osv.py @@ -12,6 +12,7 @@ from typing import Iterable from typing import List from typing import Optional +from typing import Tuple import dateparser from cvss.exceptions import CVSS3MalformedError @@ -24,6 +25,7 @@ from vulnerabilities.importer import AdvisoryData from vulnerabilities.importer import AffectedPackage from vulnerabilities.importer import AffectedPackageV2 +from vulnerabilities.importer import CodeCommitData from vulnerabilities.importer import Reference from vulnerabilities.importer import ReferenceV2 from vulnerabilities.importer import VulnerabilitySeverity @@ -83,8 +85,8 @@ def parse_advisory_data( ) for fixed_range in affected_pkg.get("ranges") or []: - fixed_version = get_fixed_versions( - fixed_range=fixed_range, raw_id=raw_id, supported_ecosystem=purl.type + fixed_version, _ = get_fixed_versions_and_commits( + ranges=fixed_range, raw_id=raw_id, supported_ecosystem=purl.type ) for version in fixed_version: @@ -131,38 +133,48 @@ def parse_advisory_data_v2( references = get_references_v2(raw_data=raw_data) affected_packages = [] - for affected_pkg in raw_data.get("affected") or []: purl = get_affected_purl(affected_pkg=affected_pkg, raw_id=advisory_id) - if not purl or purl.type not in supported_ecosystems: - logger.error(f"Unsupported package type: {affected_pkg!r} in OSV: {advisory_id!r}") - continue - - affected_version_range = get_affected_version_range( - affected_pkg=affected_pkg, - raw_id=advisory_id, - supported_ecosystem=purl.type, - ) + affected_version_range = None + if purl and purl.type in supported_ecosystems: + affected_version_range = get_affected_version_range( + affected_pkg=affected_pkg, + raw_id=advisory_id, + supported_ecosystem=purl.type, + ) fixed_versions = [] + fixed_by_commits = [] + affected_by_commits = [] fixed_version_range = None for fixed_range in affected_pkg.get("ranges") or []: - fixed_version = get_fixed_versions( - fixed_range=fixed_range, raw_id=advisory_id, supported_ecosystem=purl.type + fixed_version, (introduced_commits, fixed_commits) = get_fixed_versions_and_commits( + ranges=fixed_range, + raw_id=advisory_id, + supported_ecosystem=purl.type if purl else None, ) fixed_versions.extend([v.string for v in fixed_version]) + fixed_by_commits.extend(fixed_commits) + affected_by_commits.extend(introduced_commits) + fixed_version_range = ( get_fixed_version_range(fixed_versions, purl.type) if fixed_versions else None ) + if not purl or purl.type not in supported_ecosystems: + logger.error(f"Unsupported package type: {purl!r} in OSV: {advisory_id!r}") + continue + if fixed_version_range or affected_version_range: affected_packages.append( AffectedPackageV2( package=purl, affected_version_range=affected_version_range, fixed_version_range=fixed_version_range, + affected_by_commits=affected_by_commits, + fixed_by_commits=fixed_by_commits, ) ) @@ -187,24 +199,26 @@ def parse_advisory_data_v2( ) -def extract_fixed_versions(fixed_range) -> Iterable[str]: +def extract_introduced_and_fixed(ranges) -> Tuple[List[str], List[str]]: """ - Return a list of fixed version strings given a ``fixed_range`` mapping of - OSV data. + Return pairs of introduced and fixed versions or commit hashes given a ``ranges`` + mapping of OSV data. + + Both introduced and fixed fields may represent semantic versions or commit hashes. - >>> list(extract_fixed_versions( - ... {"type": "SEMVER", "events": [{"introduced": "0"},{"fixed": "1.6.0"}]})) - ['1.6.0'] + >>> list(extract_introduced_and_fixed( + ... {"type": "SEMVER", "events": [{"introduced": "0"}, {"fixed": "1.6.0"}]})) + [('0', None), (None, '1.6.0')] - >>> list(extract_fixed_versions( - ... {"type": "ECOSYSTEM","events":[{"introduced": "0"}, - ... {"fixed": "1.0.0"},{"fixed": "9.0.0"}]})) - ['1.0.0', '9.0.0'] + >>> list(extract_introduced_and_fixed( + ... {"type": "GIT", "events": [{"introduced": "abc123"}, + ... {"fixed": "def456"}]})) + [('abc123', None), (None, 'def456')] """ - for event in fixed_range.get("events") or []: + for event in ranges.get("events") or []: + introduced = event.get("introduced") fixed = event.get("fixed") - if fixed: - yield fixed + yield introduced, fixed def get_published_date(raw_data): @@ -338,7 +352,7 @@ def get_affected_version_range(affected_pkg, raw_id, supported_ecosystem): return RANGE_CLASS_BY_SCHEMES[supported_ecosystem].from_versions(affected_versions) except Exception as e: logger.error( - f"Invalid VersionRange for affected_pkg: {affected_pkg} " + f"Invalid VersionRange for affected_pkg: {affected_versions} " f"for OSV id: {raw_id!r}: error:{e!r}" ) @@ -350,53 +364,82 @@ def get_fixed_version_range(versions, ecosystem): logger.error(f"Failed to create VersionRange from: {versions}: error:{e!r}") -def get_fixed_versions(fixed_range, raw_id, supported_ecosystem) -> List[Version]: +def get_fixed_versions_and_commits( + ranges, raw_id, supported_ecosystem=None +) -> Tuple[List[Version], Tuple]: """ - Return a list of unique fixed univers Versions given a ``fixed_range`` - univers VersionRange and a ``raw_id``. + Extract and return all unique fixed versions and related commit data + from a given OSV vulnerability range. + For example:: - >>> get_fixed_versions(fixed_range={}, raw_id="GHSA-j3f7-7rmc-6wqj", supported_ecosystem="pypi",) - [] - >>> get_fixed_versions( - ... fixed_range={"type": "ECOSYSTEM", "events": [{"fixed": "1.7.0"}], }, + >>> get_fixed_versions_and_commits(ranges={}, raw_id="GHSA-j3f7-7rmc-6wqj", supported_ecosystem="pypi",) + ([], ([], [])) + >>> get_fixed_versions_and_commits( + ... ranges={"type": "ECOSYSTEM", "events": [{"fixed": "1.7.0"}], }, ... raw_id="GHSA-j3f7-7rmc-6wqj", ... supported_ecosystem="pypi", ... ) - [PypiVersion(string='1.7.0')] + ([PypiVersion(string='1.7.0')], ([], [])) """ fixed_versions = [] - if "type" not in fixed_range: - logger.error(f"Invalid fixed_range type for: {fixed_range} for OSV id: {raw_id!r}") - return [] + introduced_commits = [] + fixed_commits = [] + + if "type" not in ranges: + logger.error(f"Invalid range type for: {ranges} for OSV id: {raw_id!r}") + return [], ([], []) - fixed_range_type = fixed_range["type"] + fixed_range_type = ranges["type"] version_range_class = RANGE_CLASS_BY_SCHEMES.get(supported_ecosystem) version_class = version_range_class.version_class if version_range_class else None - for version in extract_fixed_versions(fixed_range): - if fixed_range_type == "ECOSYSTEM": + for introduced, fixed in extract_introduced_and_fixed(ranges): + if fixed_range_type == "ECOSYSTEM" and fixed and supported_ecosystem: try: if not version_class: raise InvalidVersion( f"Unsupported version for ecosystem: {supported_ecosystem}" ) - fixed_versions.append(version_class(version)) + fixed_versions.append(version_class(fixed)) except InvalidVersion: logger.error( - f"Invalid version class: {version_class} - {version!r} for OSV id: {raw_id!r}" + f"Invalid version class: {version_class} - {fixed!r} for OSV id: {raw_id!r}" ) - elif fixed_range_type == "SEMVER": + elif fixed_range_type == "SEMVER" and fixed and supported_ecosystem: try: - fixed_versions.append(SemverVersion(version)) + fixed_versions.append(SemverVersion(fixed)) except InvalidVersion: - logger.error(f"Invalid SemverVersion: {version!r} for OSV id: {raw_id!r}") - else: - logger.error(f"Unsupported fixed version type: {version!r} for OSV id: {raw_id!r}") + logger.error(f"Invalid SemverVersion: {fixed!r} for OSV id: {raw_id!r}") + + elif fixed_range_type == "GIT" and (fixed or introduced): + repo = ranges.get("repo") + if not repo: + logger.error(f"Missing 'repo' field in ranges: {ranges} (OSV id: {raw_id!r})") + continue + + # Git uses this magic hash for the empty tree + # See: http://colinschimmelfing.com/blog/gits-empty-tree/ + if introduced == "0": + introduced = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" + + if introduced: + try: + introduced_commit = CodeCommitData(commit_hash=introduced, vcs_url=repo) + introduced_commits.append(introduced_commit) + except ValueError as e: + logger.error(f"Failed to extract introduced commits: {e!r}") + + if fixed: + try: + fixed_commit = CodeCommitData(commit_hash=fixed, vcs_url=repo) + fixed_commits.append(fixed_commit) + except ValueError as e: + logger.error(f"Failed to extract fixed commits: {e!r}") - # if fixed_range_type == "GIT": - # TODO add GitHubVersion univers fix_version - # logger.error(f"NotImplementedError GIT Version - {raw_id !r} - {i !r}") + else: + if fixed: + logger.error(f"Unsupported fixed version type: {ranges!r} for OSV id: {raw_id!r}") - return dedupe(fixed_versions) + return dedupe(fixed_versions), (introduced_commits, fixed_commits) diff --git a/vulnerabilities/pipelines/v2_importers/pysec_importer.py b/vulnerabilities/pipelines/v2_importers/pysec_importer.py index bea79cb98..25c3e0933 100644 --- a/vulnerabilities/pipelines/v2_importers/pysec_importer.py +++ b/vulnerabilities/pipelines/v2_importers/pysec_importer.py @@ -53,7 +53,7 @@ def collect_advisories(self) -> Iterable[AdvisoryData]: for file_name in zip_file.namelist(): if not file_name.startswith("PYSEC-"): self.log( - f"Unsupported PyPI advisory data file: {file_name}", + f"Ignoring unsupported advisory data file (only PYSEC files are processed): {file_name}", level=logging.ERROR, ) continue diff --git a/vulnerabilities/pipes/advisory.py b/vulnerabilities/pipes/advisory.py index 413b260b6..6b98052e5 100644 --- a/vulnerabilities/pipes/advisory.py +++ b/vulnerabilities/pipes/advisory.py @@ -17,6 +17,7 @@ from typing import Union from django.db import transaction +from django.db.models import Q from django.db.models.query import QuerySet from vulnerabilities.importer import AdvisoryData @@ -29,6 +30,7 @@ from vulnerabilities.models import AdvisoryWeakness from vulnerabilities.models import AffectedByPackageRelatedVulnerability from vulnerabilities.models import Alias +from vulnerabilities.models import CodeCommit from vulnerabilities.models import FixingPackageRelatedVulnerability from vulnerabilities.models import Package from vulnerabilities.models import VulnerabilityReference @@ -96,6 +98,42 @@ def get_or_create_advisory_weaknesses(weaknesses: List[str]) -> List[AdvisoryWea return list(AdvisoryWeakness.objects.filter(cwe_id__in=weaknesses)) +def get_or_create_advisory_code_commits(code_commits_data: List) -> List["CodeCommit"]: + """ + Given a list of commit-like objects (each with commit_hash and vcs_url), + create any missing CodeCommit entries and return the full list of CodeCommit objects. + """ + if not code_commits_data: + return [] + + pairs = [(c.commit_hash, c.vcs_url) for c in code_commits_data] + + query = Q() + for commit_hash, vcs_url in pairs: + query |= Q(commit_hash=commit_hash, vcs_url=vcs_url) + + existing_commits_qs = CodeCommit.objects.filter(query) + existing_pairs = set(existing_commits_qs.values_list("commit_hash", "vcs_url")) + + to_create = [ + CodeCommit( + commit_hash=c.commit_hash, + vcs_url=c.vcs_url, + commit_author=getattr(c, "commit_author", None), + commit_message=getattr(c, "commit_message", None), + commit_date=getattr(c, "commit_date", None), + ) + for c in code_commits_data + if (c.commit_hash, c.vcs_url) not in existing_pairs + ] + + if to_create: + CodeCommit.objects.bulk_create(to_create, ignore_conflicts=True) + + all_commits = CodeCommit.objects.filter(query) + return list(all_commits) + + def insert_advisory(advisory: AdvisoryData, pipeline_id: str, logger: Callable = None): from vulnerabilities.utils import compute_content_id @@ -150,6 +188,7 @@ def insert_advisory_v2( severities = get_or_create_advisory_severities(severities=advisory.severities) weaknesses = get_or_create_advisory_weaknesses(weaknesses=advisory.weaknesses) content_id = compute_content_id(advisory_data=advisory) + try: default_data = { "datasource_id": pipeline_id, @@ -216,6 +255,13 @@ def insert_advisory_v2( impact.affecting_packages.add(*affected_packages_v2) impact.fixed_by_packages.add(*fixed_packages_v2) + affected_commit_v2 = get_or_create_advisory_code_commits( + affected_pkg.affected_by_commits + ) + fixed_commit_v2 = get_or_create_advisory_code_commits(affected_pkg.fixed_by_commits) + impact.affecting_commits.add(*affected_commit_v2) + impact.fixed_by_commits.add(*fixed_commit_v2) + return advisory_obj diff --git a/vulnerabilities/tests/pipelines/v2_importers/test_github_osv_importer_v2.py b/vulnerabilities/tests/pipelines/v2_importers/test_github_osv_importer_v2.py index 422d26a14..b45aeead4 100644 --- a/vulnerabilities/tests/pipelines/v2_importers/test_github_osv_importer_v2.py +++ b/vulnerabilities/tests/pipelines/v2_importers/test_github_osv_importer_v2.py @@ -13,6 +13,7 @@ import pytest from vulnerabilities.importer import AdvisoryData +from vulnerabilities.importer import CodeCommitData from vulnerabilities.pipelines.v2_importers.github_osv_importer import GithubOSVImporterPipeline @@ -27,7 +28,23 @@ def sample_osv_advisory(tmp_path: Path): { "package": {"name": "sample", "ecosystem": "pypi"}, "ranges": [ - {"type": "ECOSYSTEM", "events": [{"introduced": "1.0.0"}, {"fixed": "1.2.0"}]} + {"type": "ECOSYSTEM", "events": [{"introduced": "1.0.0"}, {"fixed": "1.2.0"}]}, + { + "type": "GIT", + "repo": "https://github.com/aboutcode-org/vulnerablecode", + "events": [ + {"introduced": "0"}, + {"fixed": "10081dd502dcfc0953de333fe8afb399db5f2a88"}, + ], + }, + { + "type": "GIT", + "repo": "https://github.com/aboutcode-org/vulnerablecode", + "events": [ + {"introduced": "b58c68c38a9de451818bac6c96d08d61e7f348a2"}, + {"fixed": "61621982593152c47b520ce893eb90c332427483"}, + ], + }, ], "versions": ["1.0.0", "1.1.0"], } @@ -67,3 +84,36 @@ def delete(self): assert advisory.original_advisory_text.strip().startswith("{") assert advisory.affected_packages assert advisory.affected_packages[0].package.type == "pypi" + assert advisory.affected_packages[0].affected_by_commits == [ + CodeCommitData( + commit_hash="4b825dc642cb6eb9a060e54bf8d69288fbee4904", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + commit_author=None, + commit_message=None, + commit_date=None, + ), + CodeCommitData( + commit_hash="b58c68c38a9de451818bac6c96d08d61e7f348a2", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + commit_author=None, + commit_message=None, + commit_date=None, + ), + ] + + assert advisory.affected_packages[0].fixed_by_commits == [ + CodeCommitData( + commit_hash="10081dd502dcfc0953de333fe8afb399db5f2a88", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + commit_author=None, + commit_message=None, + commit_date=None, + ), + CodeCommitData( + commit_hash="61621982593152c47b520ce893eb90c332427483", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + commit_author=None, + commit_message=None, + commit_date=None, + ), + ] diff --git a/vulnerabilities/tests/pipes/test_advisory.py b/vulnerabilities/tests/pipes/test_advisory.py index 72c477455..e9029d02f 100644 --- a/vulnerabilities/tests/pipes/test_advisory.py +++ b/vulnerabilities/tests/pipes/test_advisory.py @@ -19,12 +19,15 @@ from vulnerabilities import models from vulnerabilities.importer import AdvisoryData from vulnerabilities.importer import AffectedPackage +from vulnerabilities.importer import CodeCommitData from vulnerabilities.importer import Reference from vulnerabilities.models import AdvisoryAlias from vulnerabilities.models import AdvisoryReference from vulnerabilities.models import AdvisorySeverity from vulnerabilities.models import AdvisoryWeakness +from vulnerabilities.models import CodeCommit from vulnerabilities.pipes.advisory import get_or_create_advisory_aliases +from vulnerabilities.pipes.advisory import get_or_create_advisory_code_commits from vulnerabilities.pipes.advisory import get_or_create_advisory_references from vulnerabilities.pipes.advisory import get_or_create_advisory_severities from vulnerabilities.pipes.advisory import get_or_create_advisory_weaknesses @@ -43,7 +46,6 @@ def setUp(self): affected_version_range=VersionRange.from_string("vers:pypi/>=1.0.0|<=2.0.0"), ) ], - references=[Reference(url="https://example.com/with/more/info/CVE-2020-13371337")], date_published=timezone.now(), url="https://test.com", ) @@ -160,6 +162,23 @@ def advisory_references(): ] +@pytest.fixture +def advisory_commit(): + return [ + CodeCommitData( + commit_hash="ef1659c01708b2111d6f06e2aa32f0f9d8768e10", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + commit_author="tester1", + commit_message="message1", + commit_date=datetime.now(), + ), + CodeCommitData( + commit_hash="eccbb45ac2d9c0eb7e22ea82d1fc49f9f4cda818", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + ), + ] + + @pytest.fixture def advisory_severities(): class Severity: @@ -225,3 +244,13 @@ def test_get_or_create_advisory_weaknesses(advisory_weaknesses): for w in weaknesses: assert isinstance(w, AdvisoryWeakness) assert w.cwe_id in advisory_weaknesses + + +@pytest.mark.django_db +def test_get_or_create_advisory_commit(advisory_commit): + commits = get_or_create_advisory_code_commits(advisory_commit) + assert len(commits) == len(advisory_commit) + for commit in commits: + assert isinstance(commit, CodeCommit) + assert commit.commit_hash in [c.commit_hash for c in advisory_commit] + assert commit.vcs_url in [c.vcs_url for c in advisory_commit] diff --git a/vulnerabilities/tests/pipes/test_vulnerablecode_importer_pipeline_v2.py b/vulnerabilities/tests/pipes/test_vulnerablecode_importer_pipeline_v2.py index aa5a2298e..48972f76e 100644 --- a/vulnerabilities/tests/pipes/test_vulnerablecode_importer_pipeline_v2.py +++ b/vulnerabilities/tests/pipes/test_vulnerablecode_importer_pipeline_v2.py @@ -18,7 +18,9 @@ from vulnerabilities.importer import AdvisoryData from vulnerabilities.importer import AffectedPackageV2 +from vulnerabilities.importer import CodeCommitData from vulnerabilities.models import AdvisoryV2 +from vulnerabilities.models import CodeCommit from vulnerabilities.models import ImpactedPackage from vulnerabilities.models import PackageV2 from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2 @@ -51,11 +53,35 @@ def dummy_advisory(): package=PackageURL.from_string("pkg:npm/foobar"), affected_version_range=VersionRange.from_string("vers:npm/<=1.2.3"), fixed_version_range=VersionRange.from_string("vers:npm/1.2.4"), + fixed_by_commits=[ + CodeCommitData( + commit_hash="9ff29db8ec3adefefce0d37c3c9b5b2c22e59fac", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + ) + ], + affected_by_commits=[ + CodeCommitData( + commit_hash="ab99939678dc36b3bee0f366493df1aeef521df4", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + ) + ], ), AffectedPackageV2( package=PackageURL.from_string("pkg:npm/foobar"), affected_version_range=VersionRange.from_string("vers:npm/<=3.2.3"), fixed_version_range=VersionRange.from_string("vers:npm/3.2.4"), + fixed_by_commits=[ + CodeCommitData( + commit_hash="9ff29db8ec3adefefce0d37c3c9b5b2c22e59fac", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + ) + ], + affected_by_commits=[ + CodeCommitData( + commit_hash="ab99939678dc36b3bee0f366493df1aeef521df4", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + ) + ], ), ], advisory_id="ADV-123", @@ -92,4 +118,5 @@ def test_advisory_import_atomicity(dummy_importer): dummy_importer.collect_and_store_advisories() assert AdvisoryV2.objects.count() == 1 assert ImpactedPackage.objects.count() == 2 + assert CodeCommit.objects.count() == 2 assert PackageV2.objects.count() == 4 diff --git a/vulnerabilities/tests/test_data/archlinux/archlinux_advisoryv2-expected.json b/vulnerabilities/tests/test_data/archlinux/archlinux_advisoryv2-expected.json index 53923a03d..41d06366d 100644 --- a/vulnerabilities/tests/test_data/archlinux/archlinux_advisoryv2-expected.json +++ b/vulnerabilities/tests/test_data/archlinux/archlinux_advisoryv2-expected.json @@ -16,7 +16,9 @@ "subpath": "" }, "affected_version_range": "vers:alpm/2.3.0-1", - "fixed_version_range": "vers:alpm/2.4.0-1" + "fixed_version_range": "vers:alpm/2.4.0-1", + "affected_by_commits": [], + "fixed_by_commits": [] } ], "references_v2": [ @@ -50,7 +52,9 @@ "subpath": "" }, "affected_version_range": "vers:alpm/2.36.3-1", - "fixed_version_range": "vers:alpm/2.36.4-1" + "fixed_version_range": "vers:alpm/2.36.4-1", + "affected_by_commits": [], + "fixed_by_commits": [] } ], "references_v2": [ @@ -83,7 +87,9 @@ "subpath": "" }, "affected_version_range": "vers:alpm/1.0.6-5", - "fixed_version_range": "vers:alpm/1.0.6-6" + "fixed_version_range": "vers:alpm/1.0.6-6", + "affected_by_commits": [], + "fixed_by_commits": [] } ], "references_v2": [ diff --git a/vulnerabilities/tests/test_data/openssl/security_advisories-importer-expected.json b/vulnerabilities/tests/test_data/openssl/security_advisories-importer-expected.json index 60722cd00..80b684ed4 100644 --- a/vulnerabilities/tests/test_data/openssl/security_advisories-importer-expected.json +++ b/vulnerabilities/tests/test_data/openssl/security_advisories-importer-expected.json @@ -7118,7 +7118,7 @@ }, { "unique_content_id": "d87e634ab174d154043776ba4b3c6659d5f37175726b216710c42ec5144d3d95", - "summary": "Because DES (and triple-DES) has only a 64-bit block size, birthday attacks are a real concern. For example, with the ability to run Javascript in a browser, it is possible to send enough traffic to cause a collision, and then use that information to recover something like a session Cookie. Triple-DES, which shows up as \u201cDES-CBC3\u201d in an OpenSSL cipher string, is still used on the Web, and major browsers are not yet willing to completely disable it. If you run a server, you should disable triple-DES. This is generally a configuration issue. If you run an old server that doesn\u2019t support any better ciphers than DES or RC4, you should upgrade. For 1.0.2 and 1.0.1, we removed the triple-DES ciphers from the \u201cHIGH\u201d keyword and put them into \u201cMEDIUM.\u201d Note that we did not remove them from the \u201cDEFAULT\u201d keyword. For the 1.1.0 release, we treat triple-DES just like we are treating RC4. It is not compiled by default; you have to use \u201cenable-weak-ssl-ciphers\u201d as a config option. Even when those ciphers are compiled, triple-DES is only in the \u201cMEDIUM\u201d keyword. In addition we also removed it from the \u201cDEFAULT\u201d keyword.", + "summary": "Because DES (and triple-DES) has only a 64-bit block size, birthday attacks are a real concern. For example, with the ability to run Javascript in a browser, it is possible to send enough traffic to cause a collision, and then use that information to recover something like a session Cookie. Triple-DES, which shows up as “DES-CBC3” in an OpenSSL cipher string, is still used on the Web, and major browsers are not yet willing to completely disable it. If you run a server, you should disable triple-DES. This is generally a configuration issue. If you run an old server that doesn’t support any better ciphers than DES or RC4, you should upgrade. For 1.0.2 and 1.0.1, we removed the triple-DES ciphers from the “HIGH” keyword and put them into “MEDIUM.” Note that we did not remove them from the “DEFAULT” keyword. For the 1.1.0 release, we treat triple-DES just like we are treating RC4. It is not compiled by default; you have to use “enable-weak-ssl-ciphers” as a config option. Even when those ciphers are compiled, triple-DES is only in the “MEDIUM” keyword. In addition we also removed it from the “DEFAULT” keyword.", "affected_packages": [ { "package": { diff --git a/vulnerabilities/tests/test_data/redhat/redhat_advisoryv2-expected.json b/vulnerabilities/tests/test_data/redhat/redhat_advisoryv2-expected.json index 7a0a1c565..1d6af8a6b 100644 --- a/vulnerabilities/tests/test_data/redhat/redhat_advisoryv2-expected.json +++ b/vulnerabilities/tests/test_data/redhat/redhat_advisoryv2-expected.json @@ -23,7 +23,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -35,7 +37,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -47,7 +51,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -59,7 +65,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -71,7 +79,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -83,7 +93,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -95,7 +107,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -107,7 +121,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -119,7 +135,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -131,7 +149,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -143,7 +163,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -155,7 +177,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -167,7 +191,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<4.6-3.el9_0.3", - "fixed_version_range": "vers:rpm/4.6-3.el9_0.3" + "fixed_version_range": "vers:rpm/4.6-3.el9_0.3", + "affected_by_commits": [], + "fixed_by_commits": [] } ], "references_v2": [ @@ -329,7 +355,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<20230808-2.20250211.1.el9_4", - "fixed_version_range": "vers:rpm/20230808-2.20250211.1.el9_4" + "fixed_version_range": "vers:rpm/20230808-2.20250211.1.el9_4", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -341,7 +369,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<20230808-2.20250211.1.el9_4", - "fixed_version_range": "vers:rpm/20230808-2.20250211.1.el9_4" + "fixed_version_range": "vers:rpm/20230808-2.20250211.1.el9_4", + "affected_by_commits": [], + "fixed_by_commits": [] } ], "references_v2": [ @@ -384,7 +414,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -396,7 +428,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -408,7 +442,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -420,7 +456,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -432,7 +470,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -444,7 +484,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -456,7 +498,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -468,7 +512,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -480,7 +526,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -492,7 +540,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -504,7 +554,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -516,7 +568,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -528,7 +582,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -540,7 +596,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -552,7 +610,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -564,7 +624,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -576,7 +638,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -588,7 +652,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -600,7 +666,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -612,7 +680,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -624,7 +694,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -636,7 +708,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.4-4.el5_4.2", - "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2" + "fixed_version_range": "vers:rpm/0.8.4-4.el5_4.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -648,7 +722,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -660,7 +736,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.8.3-6.el4_8.2", - "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2" + "fixed_version_range": "vers:rpm/0.8.3-6.el4_8.2", + "affected_by_commits": [], + "fixed_by_commits": [] } ], "references_v2": [ @@ -713,7 +791,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.3.7-30.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/1.3.7-30.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/1.3.7-30.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -725,7 +805,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -737,7 +819,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.3.2-2.module+el8.4.0+20979+8ba06d83.1", - "fixed_version_range": "vers:rpm/1.3.2-2.module+el8.4.0+20979+8ba06d83.1" + "fixed_version_range": "vers:rpm/1.3.2-2.module+el8.4.0+20979+8ba06d83.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -749,7 +833,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<15.1.0-19.module+el8.4.0+22650+01781d50.3", - "fixed_version_range": "vers:rpm/15.1.0-19.module+el8.4.0+22650+01781d50.3" + "fixed_version_range": "vers:rpm/15.1.0-19.module+el8.4.0+22650+01781d50.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -761,7 +847,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.10.1-2.module+el8.4.0+9657+a4b6a102", - "fixed_version_range": "vers:rpm/0.10.1-2.module+el8.4.0+9657+a4b6a102" + "fixed_version_range": "vers:rpm/0.10.1-2.module+el8.4.0+9657+a4b6a102", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -773,7 +861,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.4.0-2.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/1.4.0-2.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/1.4.0-2.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -785,7 +875,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.7-2.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/3.6.7-2.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/3.6.7-2.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -797,7 +889,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.14-12.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/0.14-12.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/0.14-12.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -809,7 +903,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.3.7-30.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/1.3.7-30.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/1.3.7-30.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -821,7 +917,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<2.2.0-20.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/2.2.0-20.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/2.2.0-20.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -833,7 +931,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<15.1.0-19.module+el8.4.0+22650+01781d50.3", - "fixed_version_range": "vers:rpm/15.1.0-19.module+el8.4.0+22650+01781d50.3" + "fixed_version_range": "vers:rpm/15.1.0-19.module+el8.4.0+22650+01781d50.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -845,7 +945,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.31.1-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/0.31.1-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/0.31.1-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -857,7 +959,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.31.1-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/0.31.1-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/0.31.1-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -869,7 +973,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.8-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -881,7 +987,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.10.1-2.module+el8.4.0+9657+a4b6a102", - "fixed_version_range": "vers:rpm/0.10.1-2.module+el8.4.0+9657+a4b6a102" + "fixed_version_range": "vers:rpm/0.10.1-2.module+el8.4.0+9657+a4b6a102", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -893,7 +1001,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.4.0-2.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/1.4.0-2.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/1.4.0-2.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -905,7 +1015,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.7-2.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/3.6.7-2.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/3.6.7-2.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -917,7 +1029,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.14-12.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/0.14-12.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/0.14-12.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -929,7 +1043,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.3.7-30.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/1.3.7-30.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/1.3.7-30.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -941,7 +1057,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<2.2.0-20.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/2.2.0-20.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/2.2.0-20.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -953,7 +1071,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -965,7 +1085,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.3.2-2.module+el8.4.0+20979+8ba06d83.1", - "fixed_version_range": "vers:rpm/1.3.2-2.module+el8.4.0+20979+8ba06d83.1" + "fixed_version_range": "vers:rpm/1.3.2-2.module+el8.4.0+20979+8ba06d83.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -977,7 +1099,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<15.1.0-19.module+el8.4.0+22650+01781d50.3", - "fixed_version_range": "vers:rpm/15.1.0-19.module+el8.4.0+22650+01781d50.3" + "fixed_version_range": "vers:rpm/15.1.0-19.module+el8.4.0+22650+01781d50.3", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -989,7 +1113,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<0.31.1-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/0.31.1-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/0.31.1-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1001,7 +1127,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.8-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1013,7 +1141,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.0.0-20.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1025,7 +1155,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1037,7 +1169,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1049,7 +1183,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1061,7 +1197,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1073,7 +1211,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1085,7 +1225,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1097,7 +1239,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1109,7 +1253,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.0.0-20.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1121,7 +1267,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.0.0-20.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1133,7 +1281,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.3.2-2.module+el8.4.0+20979+8ba06d83.1", - "fixed_version_range": "vers:rpm/1.3.2-2.module+el8.4.0+20979+8ba06d83.1" + "fixed_version_range": "vers:rpm/1.3.2-2.module+el8.4.0+20979+8ba06d83.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1145,7 +1295,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.8-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1157,7 +1309,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.8-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1169,7 +1323,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.8-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1181,7 +1337,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.0.0-20.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1193,7 +1351,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1205,7 +1365,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1217,7 +1379,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1229,7 +1393,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1241,7 +1407,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1253,7 +1421,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1265,7 +1435,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.7.0-1.module+el8.4.0+9670+1849b5f9", - "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9" + "fixed_version_range": "vers:rpm/3.7.0-1.module+el8.4.0+9670+1849b5f9", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1277,7 +1449,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.0.0-20.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1289,7 +1463,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.0.0-20.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1301,7 +1477,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.3.2-2.module+el8.4.0+20979+8ba06d83.1", - "fixed_version_range": "vers:rpm/1.3.2-2.module+el8.4.0+20979+8ba06d83.1" + "fixed_version_range": "vers:rpm/1.3.2-2.module+el8.4.0+20979+8ba06d83.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1313,7 +1491,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.8-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1325,7 +1505,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.8-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1337,7 +1519,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<3.6.8-2.module+el8.4.0+15040+36b018e7.1", - "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1" + "fixed_version_range": "vers:rpm/3.6.8-2.module+el8.4.0+15040+36b018e7.1", + "affected_by_commits": [], + "fixed_by_commits": [] }, { "package": { @@ -1349,7 +1533,9 @@ "subpath": "" }, "affected_version_range": "vers:rpm/<1.0.0-20.module+el8.1.0+3334+5cb623d7", - "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7" + "fixed_version_range": "vers:rpm/1.0.0-20.module+el8.1.0+3334+5cb623d7", + "affected_by_commits": [], + "fixed_by_commits": [] } ], "references_v2": [ diff --git a/vulnerabilities/tests/test_osv.py b/vulnerabilities/tests/test_osv.py index e7505510c..4121b507e 100644 --- a/vulnerabilities/tests/test_osv.py +++ b/vulnerabilities/tests/test_osv.py @@ -15,12 +15,13 @@ from univers.versions import PypiVersion from univers.versions import SemverVersion +from vulnerabilities.importer import CodeCommitData from vulnerabilities.importer import Reference from vulnerabilities.importer import VulnerabilitySeverity -from vulnerabilities.importers.osv import extract_fixed_versions as fixed_filter +from vulnerabilities.importers.osv import extract_introduced_and_fixed as fixed_filter from vulnerabilities.importers.osv import get_affected_purl from vulnerabilities.importers.osv import get_affected_version_range -from vulnerabilities.importers.osv import get_fixed_versions +from vulnerabilities.importers.osv import get_fixed_versions_and_commits from vulnerabilities.importers.osv import get_published_date from vulnerabilities.importers.osv import get_references from vulnerabilities.importers.osv import get_severities @@ -31,15 +32,15 @@ class TestOSVImporter(TestCase): def test_fixed_filter1(self): results = list( fixed_filter( - fixed_range={"type": "SEMVER", "events": [{"introduced": "0"}, {"fixed": "1.6.0"}]} + ranges={"type": "SEMVER", "events": [{"introduced": "0"}, {"fixed": "1.6.0"}]} ) ) - assert results == ["1.6.0"] + assert results == [("0", None), (None, "1.6.0")] def test_fixed_filter2(self): results = list( fixed_filter( - fixed_range={ + ranges={ "type": "ECOSYSTEM", "events": [ {"introduced": "0"}, @@ -50,12 +51,12 @@ def test_fixed_filter2(self): } ) ) - assert results == ["1.0.0", "9.0.0"] + assert results == [("0", None), (None, "1.0.0"), ("0", None), (None, "9.0.0")] def test_fixed_filter3(self): results = list( fixed_filter( - fixed_range={ + ranges={ "type": "ECOSYSTEM", "events": [ {"introduced": "1.5.0"}, @@ -68,7 +69,14 @@ def test_fixed_filter3(self): } ) ) - assert results == ["1.5.0", "9.0g0", "10.8"] + assert results == [ + ("1.5.0", None), + (None, "1.5.0"), + ("4.01", None), + (None, "9.0g0"), + ("8.0.4", None), + (None, "10.8"), + ] def test_get_published_date1(self): results = get_published_date( @@ -354,24 +362,21 @@ def test_get_affected_version_range(self): assert results == expected def test_get_fixed_versions1(self): - assert ( - get_fixed_versions( - fixed_range={}, raw_id="GHSA-j3f7-7rmc-6wqj", supported_ecosystem="pypi" - ) - == [] - ) + assert get_fixed_versions_and_commits( + ranges={}, raw_id="GHSA-j3f7-7rmc-6wqj", supported_ecosystem="pypi" + ) == ([], ([], [])) def test_get_fixed_versions2(self): - results = get_fixed_versions( - fixed_range={"type": "ECOSYSTEM", "events": [{"introduced": "0"}, {"fixed": "1.7.0"}]}, + results = get_fixed_versions_and_commits( + ranges={"type": "ECOSYSTEM", "events": [{"introduced": "0"}, {"fixed": "1.7.0"}]}, raw_id="GHSA-j3f7-7rmc-6wqj", supported_ecosystem="pypi", ) - assert results == [PypiVersion("1.7.0")] + assert results == ([PypiVersion(string="1.7.0")], ([], [])) def test_get_fixed_versions3(self): - results = get_fixed_versions( - fixed_range={ + results = get_fixed_versions_and_commits( + ranges={ "type": "ECOSYSTEM", "events": [ {"introduced": "0"}, @@ -384,11 +389,11 @@ def test_get_fixed_versions3(self): supported_ecosystem="pypi", ) - assert results == [PypiVersion("9.0.0"), PypiVersion("9.0.1")] + assert results == ([PypiVersion(string="9.0.0"), PypiVersion(string="9.0.1")], ([], [])) def test_get_fixed_versions4(self): - results = get_fixed_versions( - fixed_range={ + results = get_fixed_versions_and_commits( + ranges={ "type": "ECOSYSTEM", "events": [{"introduced": "0"}, {"fixed": "6.5.4"}], }, @@ -396,4 +401,68 @@ def test_get_fixed_versions4(self): supported_ecosystem="npm", ) - assert results == [SemverVersion("6.5.4")] + assert results == ([SemverVersion(string="6.5.4")], ([], [])) + + def test_fixed_filter4(self): + results = get_fixed_versions_and_commits( + ranges={ + "type": "GIT", + "repo": "https://github.com/aboutcode-org/vulnerablecode", + "events": [ + {"introduced": "0"}, + {"fixed": "a8ec9f1f300dc87f24e0f0a426a5c67c0b1b32d7"}, + ], + }, + raw_id="GHSA-j3f7-7rmc-6wqj", + ) + + assert results == ( + [], + ( + [ + CodeCommitData( + commit_hash="4b825dc642cb6eb9a060e54bf8d69288fbee4904", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + commit_author=None, + commit_message=None, + commit_date=None, + ) + ], + [ + CodeCommitData( + commit_hash="a8ec9f1f300dc87f24e0f0a426a5c67c0b1b32d7", + vcs_url="https://github.com/aboutcode-org/vulnerablecode", + commit_author=None, + commit_message=None, + commit_date=None, + ) + ], + ), + ) + + def test_invalid_filter(self): + results = get_fixed_versions_and_commits( + ranges={ + "type": "GIT", + "events": [ + {"introduced": "0"}, + {"fixed": "a8ec9f1f300dc87f24e0f0a426a5c67c0b1b32d7"}, + ], + }, + raw_id="GHSA-j3f7-7rmc-6wqj", + ) + + assert results == ([], ([], [])) # no vcs_url + + results = get_fixed_versions_and_commits( + ranges={ + "repo": "https://github.com/aboutcode-org/vulnerablecode", + "events": [ + {"introduced": "0"}, + {"fixed": "a8ec9f1f300dc87f24e0f0a426a5c67c0b1b32d7"}, + ], + }, + raw_id="GHSA-j3f7-7rmc-6wqj", + ) + + assert results == ([], ([], [])) # no type diff --git a/vulnerabilities/utils.py b/vulnerabilities/utils.py index b65726a5d..bc87af834 100644 --- a/vulnerabilities/utils.py +++ b/vulnerabilities/utils.py @@ -48,6 +48,9 @@ find_all_cve = cve_regex.findall cwe_regex = r"CWE-\d+" +commit_regex = re.compile(r"\b[0-9a-f]{5,40}\b", re.IGNORECASE) +is_commit = commit_regex.fullmatch + @dataclasses.dataclass(order=True, frozen=True) class AffectedPackage: