diff --git a/vulnerabilities/importers/__init__.py b/vulnerabilities/importers/__init__.py index b0b1ccb52..83a8abf6a 100644 --- a/vulnerabilities/importers/__init__.py +++ b/vulnerabilities/importers/__init__.py @@ -49,6 +49,7 @@ elixir_security_importer as elixir_security_importer_v2, ) from vulnerabilities.pipelines.v2_importers import epss_importer_v2 +from vulnerabilities.pipelines.v2_importers import gentoo_importer as gentoo_importer_v2 from vulnerabilities.pipelines.v2_importers import github_osv_importer as github_osv_importer_v2 from vulnerabilities.pipelines.v2_importers import gitlab_importer as gitlab_importer_v2 from vulnerabilities.pipelines.v2_importers import istio_importer as istio_importer_v2 @@ -88,6 +89,7 @@ aosp_importer_v2.AospImporterPipeline, ruby_importer_v2.RubyImporterPipeline, epss_importer_v2.EPSSImporterPipeline, + gentoo_importer_v2.GentooImporterPipeline, mattermost_importer_v2.MattermostImporterPipeline, nvd_importer.NVDImporterPipeline, github_importer.GitHubAPIImporterPipeline, diff --git a/vulnerabilities/pipelines/v2_importers/gentoo_importer.py b/vulnerabilities/pipelines/v2_importers/gentoo_importer.py new file mode 100644 index 000000000..61798147c --- /dev/null +++ b/vulnerabilities/pipelines/v2_importers/gentoo_importer.py @@ -0,0 +1,192 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# VulnerableCode is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +# See https://github.com/aboutcode-org/vulnerablecode for support or download. +# See https://aboutcode.org for more information about nexB OSS projects. +# + +import re +import xml.etree.ElementTree as ET +from pathlib import Path +from typing import Iterable + +from fetchcode.vcs import fetch_via_vcs +from packageurl import PackageURL +from univers.version_constraint import VersionConstraint +from univers.version_range import EbuildVersionRange +from univers.versions import GentooVersion +from univers.versions import InvalidVersion + +from vulnerabilities.importer import AdvisoryData +from vulnerabilities.importer import AffectedPackageV2 +from vulnerabilities.importer import ReferenceV2 +from vulnerabilities.importer import VulnerabilitySeverity +from vulnerabilities.management.commands.commit_export import logger +from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2 +from vulnerabilities.severity_systems import GENERIC + + +class GentooImporterPipeline(VulnerableCodeBaseImporterPipelineV2): + repo_url = "git+https://anongit.gentoo.org/git/data/glsa.git" + spdx_license_expression = "CC-BY-SA-4.0" + # the license notice is at this url https://anongit.gentoo.org/ says: + # The contents of this document, unless otherwise expressly stated, are licensed + # under the [CC-BY-SA-4.0](https://creativecommons.org/licenses/by-sa/4.0/) license. + license_url = "https://creativecommons.org/licenses/by-sa/4.0/" + pipeline_id = "gentoo_importer_v2" + + @classmethod + def steps(cls): + return ( + cls.clone, + cls.collect_and_store_advisories, + cls.clean_downloads, + ) + + def clone(self): + self.log(f"Cloning `{self.repo_url}`") + self.vcs_response = fetch_via_vcs(self.repo_url) + + def advisories_count(self): + advisory_dir = Path(self.vcs_response.dest_dir) + return sum(1 for _ in advisory_dir.rglob("*.xml")) + + def collect_advisories(self) -> Iterable[AdvisoryData]: + base_path = Path(self.vcs_response.dest_dir) + for file_path in base_path.glob("**/*.xml"): + yield from self.process_file(file_path) + + def process_file(self, file): + cves = [] + summary = "" + xml_root = ET.parse(file).getroot() + id = xml_root.attrib.get("id") + glsa = "GLSA-" + id + + vuln_references = [ + ReferenceV2( + reference_id=glsa, + url=f"https://security.gentoo.org/glsa/{id}", + ) + ] + + severities = [] + affected_packages = [] + for child in xml_root: + if child.tag == "references": + cves = self.cves_from_reference(child) + + if child.tag == "synopsis": + summary = child.text + + if child.tag == "affected": + affected_packages = list(affected_and_safe_purls(child)) + + if child.tag == "impact": + severity_value = child.attrib.get("type") + if severity_value: + severities.append(VulnerabilitySeverity(system=GENERIC, value=severity_value)) + + yield AdvisoryData( + advisory_id=glsa, + aliases=cves, + summary=summary, + references_v2=vuln_references, + severities=severities, + affected_packages=affected_packages, + url=f"https://security.gentoo.org/glsa/{id}" + if id + else "https://security.gentoo.org/glsa", + original_advisory_text=file, + ) + + def clean_downloads(self): + if self.vcs_response: + self.log("Removing cloned repository") + self.vcs_response.delete() + + def on_failure(self): + self.clean_downloads() + + @staticmethod + def cves_from_reference(reference): + cves = [] + for child in reference: + txt = child.text.strip() + match = re.match(r"CVE-\d{4}-\d{4,}", txt) + if match: + cves.append(match.group()) + return cves + + +def affected_and_safe_purls(affected_elem): + constraints = [] + for pkg in affected_elem: + name = pkg.attrib.get("name") + if not name: + continue + pkg_ns, _, pkg_name = name.rpartition("/") + purl = PackageURL(type="ebuild", name=pkg_name, namespace=pkg_ns) + safe_versions, affected_versions = get_safe_and_affected_versions(pkg) + + for version in safe_versions: + try: + constraints.append( + VersionConstraint(version=GentooVersion(version), comparator="=").invert() + ) + except InvalidVersion as e: + logger.error(f"InvalidVersion - version: {version} - error:{e}") + + for version in affected_versions: + try: + constraints.append( + VersionConstraint(version=GentooVersion(version), comparator="=") + ) + except InvalidVersion as e: + logger.error(f"InvalidVersion - version: {version} - error:{e}") + + if not constraints: + continue + + yield AffectedPackageV2( + package=purl, + affected_version_range=EbuildVersionRange(constraints=constraints), + fixed_version_range=None, + ) + + +def get_safe_and_affected_versions(pkg): + # TODO : Revisit why we are skipping some versions in gentoo importer + skip_versions = {"1.3*", "7.3*", "7.4*"} + safe_versions = set() + affected_versions = set() + for info in pkg: + if info.text in skip_versions: + continue + + if info.attrib.get("range"): + if len(info.attrib.get("range")) > 2: + continue + + if info.tag == "unaffected": + # quick hack, to know whether this + # version lies in this range, 'e' stands for + # equal, which is paired with 'greater' or 'less'. + # All possible values of info.attrib['range'] = + # {'gt', 'lt', 'rle', 'rge', 'rgt', 'le', 'ge', 'eq'}, out of + # which ('rle', 'rge', 'rgt') are ignored, because they compare + # 'release' not the 'version'. + if "e" in info.attrib["range"]: + safe_versions.add(info.text) + else: + affected_versions.add(info.text) + + elif info.tag == "vulnerable": + if "e" in info.attrib["range"]: + affected_versions.add(info.text) + else: + safe_versions.add(info.text) + + return safe_versions, affected_versions diff --git a/vulnerabilities/tests/pipelines/v2_importers/test_gentoo_importer_v2.py b/vulnerabilities/tests/pipelines/v2_importers/test_gentoo_importer_v2.py new file mode 100644 index 000000000..c8206a499 --- /dev/null +++ b/vulnerabilities/tests/pipelines/v2_importers/test_gentoo_importer_v2.py @@ -0,0 +1,38 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# VulnerableCode is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +# See https://github.com/aboutcode-org/vulnerablecode for support or download. +# See https://aboutcode.org for more information about nexB OSS projects. +# + +from pathlib import Path +from unittest.mock import Mock +from unittest.mock import patch + +import pytest + +from vulnerabilities.pipelines.v2_importers.gentoo_importer import GentooImporterPipeline +from vulnerabilities.tests import util_tests + +TEST_DATA = Path(__file__).parent.parent.parent / "test_data" / "gentoo_v2" + +TEST_CVE_FILES = [ + TEST_DATA / "glsa-201709-09.xml", + TEST_DATA / "glsa-202511-02.xml", + TEST_DATA / "glsa-202512-01.xml", +] + + +@pytest.mark.django_db +@pytest.mark.parametrize("xml_file", TEST_CVE_FILES) +def test_gentoo_advisories_per_file(xml_file): + pipeline = GentooImporterPipeline() + pipeline.vcs_response = Mock(dest_dir=TEST_DATA) + + with patch.object(Path, "glob", return_value=[xml_file]): + result = [adv.to_dict() for adv in pipeline.collect_advisories()] + + expected_file = xml_file.with_name(xml_file.stem + "-expected.json") + util_tests.check_results_against_json(result, expected_file) diff --git a/vulnerabilities/tests/test_data/gentoo_v2/glsa-201709-09-expected.json b/vulnerabilities/tests/test_data/gentoo_v2/glsa-201709-09-expected.json new file mode 100644 index 000000000..d11fedce3 --- /dev/null +++ b/vulnerabilities/tests/test_data/gentoo_v2/glsa-201709-09-expected.json @@ -0,0 +1,43 @@ +[ + { + "advisory_id": "GLSA-201709-09", + "aliases": [ + "CVE-2017-9800" + ], + "summary": "A command injection vulnerability in Subversion may allow remote\n attackers to execute arbitrary code.", + "affected_packages": [ + { + "package": { + "type": "ebuild", + "namespace": "dev-vcs", + "name": "subversion", + "version": "", + "qualifiers": "", + "subpath": "" + }, + "affected_version_range": "vers:ebuild/0.1.1|!=1.9.7", + "fixed_version_range": null, + "introduced_by_commit_patches": [], + "fixed_by_commit_patches": [] + } + ], + "references_v2": [ + { + "reference_id": "GLSA-201709-09", + "reference_type": "", + "url": "https://security.gentoo.org/glsa/201709-09" + } + ], + "patches": [], + "severities": [ + { + "system": "generic_textual", + "value": "normal", + "scoring_elements": "" + } + ], + "date_published": null, + "weaknesses": [], + "url": "https://security.gentoo.org/glsa/201709-09" + } +] \ No newline at end of file diff --git a/vulnerabilities/tests/test_data/gentoo_v2/glsa-201709-09.xml b/vulnerabilities/tests/test_data/gentoo_v2/glsa-201709-09.xml new file mode 100644 index 000000000..728e6898d --- /dev/null +++ b/vulnerabilities/tests/test_data/gentoo_v2/glsa-201709-09.xml @@ -0,0 +1,77 @@ + + + + Subversion: Arbitrary code execution + A command injection vulnerability in Subversion may allow remote + attackers to execute arbitrary code. + + subversion + 2017-09-17 + 2017-09-17 + 627480 + remote + + + 1.9.7 + 1.8.18 + 1.9.7 + 0.1.1 + + + + +

Subversion is a version control system intended to eventually replace + CVS. Like CVS, it has an optional client-server architecture (where the + server can be an Apache server running mod_svn, or an ssh program as in + CVS’s :ext: method). In addition to supporting the features found in + CVS, Subversion also provides support for moving and copying files and + directories. +

+
+ +

Specially crafted ‘ssh://...’ URLs may allow the owner of the + repository to execute arbitrary commands on client’s machine if those + commands are already installed on the client’s system. This is + especially dangerous when the third-party repository has one or more + submodules with specially crafted ‘ssh://...’ URLs. Each time the + repository is recursively cloned or submodules are updated the payload + will be triggered. +

+
+ +

A remote attacker, by enticing a user to clone a specially crafted + repository, could possibly execute arbitrary code with the privileges of + the process. +

+
+ +

There are several alternative ways to fix this vulnerability. Please + refer to Subversion Team Announce for more details. +

+
+ +

All Subversion 1.9.x users should upgrade to the latest version:

+ + + # emerge --sync + # emerge --ask --oneshot --verbose ">=dev-vcs/subversion-1.9.7" + + +

All Subversion 1.8.x users should upgrade to the latest version:

+ + + # emerge --sync + # emerge --ask --oneshot --verbose ">=dev-vcs/subversion-1.8.18" + +
+ + + CVE-2017-9800 + + + Subversion Team Announce + + + b-man + chrisadr +
diff --git a/vulnerabilities/tests/test_data/gentoo_v2/glsa-202511-02-expected.json b/vulnerabilities/tests/test_data/gentoo_v2/glsa-202511-02-expected.json new file mode 100644 index 000000000..5b4ac8e9e --- /dev/null +++ b/vulnerabilities/tests/test_data/gentoo_v2/glsa-202511-02-expected.json @@ -0,0 +1,67 @@ +[ + { + "advisory_id": "GLSA-202511-02", + "aliases": [ + "CVE-2024-40857", + "CVE-2024-40866", + "CVE-2024-44185", + "CVE-2024-44187", + "CVE-2024-44192", + "CVE-2024-44244", + "CVE-2024-44296", + "CVE-2024-54467", + "CVE-2024-54551", + "CVE-2025-24201", + "CVE-2025-24208", + "CVE-2025-24209", + "CVE-2025-24213", + "CVE-2025-24216", + "CVE-2025-24264", + "CVE-2025-30427", + "CVE-2025-31273", + "CVE-2025-31278", + "CVE-2025-43211", + "CVE-2025-43212", + "CVE-2025-43216", + "CVE-2025-43227", + "CVE-2025-43228", + "CVE-2025-43240", + "CVE-2025-43265" + ], + "summary": "Multiple vulnerabilities have been discovered in WebKitGTK+, the worst of which can lead to execution of arbitary code.", + "affected_packages": [ + { + "package": { + "type": "ebuild", + "namespace": "net-libs", + "name": "webkit-gtk", + "version": "", + "qualifiers": "", + "subpath": "" + }, + "affected_version_range": "vers:ebuild/!=2.48.5", + "fixed_version_range": null, + "introduced_by_commit_patches": [], + "fixed_by_commit_patches": [] + } + ], + "references_v2": [ + { + "reference_id": "GLSA-202511-02", + "reference_type": "", + "url": "https://security.gentoo.org/glsa/202511-02" + } + ], + "patches": [], + "severities": [ + { + "system": "generic_textual", + "value": "high", + "scoring_elements": "" + } + ], + "date_published": null, + "weaknesses": [], + "url": "https://security.gentoo.org/glsa/202511-02" + } +] \ No newline at end of file diff --git a/vulnerabilities/tests/test_data/gentoo_v2/glsa-202511-02.xml b/vulnerabilities/tests/test_data/gentoo_v2/glsa-202511-02.xml new file mode 100644 index 000000000..8f541908a --- /dev/null +++ b/vulnerabilities/tests/test_data/gentoo_v2/glsa-202511-02.xml @@ -0,0 +1,73 @@ + + + + WebKitGTK+: Multiple Vulnerabilities + Multiple vulnerabilities have been discovered in WebKitGTK+, the worst of which can lead to execution of arbitary code. + webkit-gtk + 2025-11-24 + 2025-11-24 + 938026 + 941276 + 951739 + 961021 + remote + + + 2.48.5 + 2.48.5 + 2.48.5 + 2.48.5 + + + +

WebKitGTK+ is a full-featured port of the WebKit rendering engine, suitable for projects requiring any kind of web integration, from hybrid HTML/CSS applications to full-fledged web browsers.

+
+ +

Multiple vulnerabilities have been discovered in WebKitGTK+. Please review the CVE identifiers referenced below for details.

+
+ +

Please review the referenced CVE identifiers for details.

+
+ +

There is no known workaround at this time.

+
+ +

All WebKitGTK+ users should upgrade to the latest version:

+ + + # emerge --sync + # emerge --ask --oneshot --verbose ">=net-libs/webkit-gtk-2.48.5:4.1" ">=net-libs/webkit-gtk-2.48.5:6" + +
+ + CVE-2024-40857 + CVE-2024-40866 + CVE-2024-44185 + CVE-2024-44187 + CVE-2024-44192 + CVE-2024-44244 + CVE-2024-44296 + CVE-2024-54467 + CVE-2024-54551 + CVE-2025-24201 + CVE-2025-24208 + CVE-2025-24209 + CVE-2025-24213 + CVE-2025-24216 + CVE-2025-24264 + CVE-2025-30427 + CVE-2025-31273 + CVE-2025-31278 + CVE-2025-43211 + CVE-2025-43212 + CVE-2025-43216 + CVE-2025-43227 + CVE-2025-43228 + CVE-2025-43240 + CVE-2025-43265 + WSA-2025-0002 + WSA-2025-0003 + + graaff + sam +
\ No newline at end of file diff --git a/vulnerabilities/tests/test_data/gentoo_v2/glsa-202512-01-expected.json b/vulnerabilities/tests/test_data/gentoo_v2/glsa-202512-01-expected.json new file mode 100644 index 000000000..38b9773c4 --- /dev/null +++ b/vulnerabilities/tests/test_data/gentoo_v2/glsa-202512-01-expected.json @@ -0,0 +1,41 @@ +[ + { + "advisory_id": "GLSA-202512-01", + "aliases": [], + "summary": "A vulnerability has been discovered in GnuPG, which can lead to arbitrary code execution.", + "affected_packages": [ + { + "package": { + "type": "ebuild", + "namespace": "app-crypt", + "name": "gnupg", + "version": "", + "qualifiers": "", + "subpath": "" + }, + "affected_version_range": "vers:ebuild/!=2.5.14", + "fixed_version_range": null, + "introduced_by_commit_patches": [], + "fixed_by_commit_patches": [] + } + ], + "references_v2": [ + { + "reference_id": "GLSA-202512-01", + "reference_type": "", + "url": "https://security.gentoo.org/glsa/202512-01" + } + ], + "patches": [], + "severities": [ + { + "system": "generic_textual", + "value": "high", + "scoring_elements": "" + } + ], + "date_published": null, + "weaknesses": [], + "url": "https://security.gentoo.org/glsa/202512-01" + } +] \ No newline at end of file diff --git a/vulnerabilities/tests/test_data/gentoo_v2/glsa-202512-01.xml b/vulnerabilities/tests/test_data/gentoo_v2/glsa-202512-01.xml new file mode 100644 index 000000000..d4a6b6b9d --- /dev/null +++ b/vulnerabilities/tests/test_data/gentoo_v2/glsa-202512-01.xml @@ -0,0 +1,41 @@ + + + + GnuPG: Arbitrary Code Execution + A vulnerability has been discovered in GnuPG, which can lead to arbitrary code execution. + gnupg + 2025-12-27 + 2025-12-27 + 967884 + remote + + + 2.5.14 + 2.5.14 + + + +

The GNU Privacy Guard, GnuPG, is a free replacement for the PGP suite of cryptographic software.

+
+ +

A vulnerability has been discovered in GnuPG's armor parser.

+
+ +

A remote attacker could entice a user or automated system to process a specially crafted signature file, possibly resulting in execution of arbitrary commands with the privileges of the process.

+
+ +

There is no known workaround at this time.

+
+ +

All GnuPG users should upgrade to the latest version:

+ + + # emerge --sync + # emerge --ask --oneshot --verbose ">=app-crypt/gnupg-2.5.14" + +
+ + + sam + sam +
\ No newline at end of file