From 0d56b219c46bcb418d697d2b0ca258bbcae43485 Mon Sep 17 00:00:00 2001 From: Ghxst <200635707+GHX5T-SOL@users.noreply.github.com> Date: Mon, 25 May 2026 20:33:22 +0200 Subject: [PATCH] Update OSS Index datasource for Sonatype Guide Signed-off-by: Ghxst <200635707+GHX5T-SOL@users.noreply.github.com> --- vulntotal/datasources/oss_index.py | 11 ++++----- vulntotal/tests/test_oss_index.py | 36 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/vulntotal/datasources/oss_index.py b/vulntotal/datasources/oss_index.py index a18e65d21..2277250ad 100644 --- a/vulntotal/datasources/oss_index.py +++ b/vulntotal/datasources/oss_index.py @@ -23,17 +23,18 @@ class OSSDataSource(DataSource): spdx_license_expression = "TODO" license_url = "TODO" - api_unauthenticated = "https://ossindex.sonatype.org/api/v3/component-report" - api_authenticated = "https://ossindex.sonatype.org/api/v3/authorized/component-report" + api_unauthenticated = "https://api.guide.sonatype.com/api/v3/component-report" + api_authenticated = "https://api.guide.sonatype.com/api/v3/authorized/component-report" def fetch_json_response(self, coordinates): - """Fetch JSON response from OSS Index API for a given list of coordinates. + """Fetch JSON response from the Sonatype Guide OSS Index compatibility API. Parameters: coordinates: A list of strings representing the package coordinates. Returns: - A dictionary containing the JSON response from the OSS Index API, or None if the response is unsuccessful or an error occurs while fetching data. + A dictionary containing the JSON response from the compatibility API, or None + if the response is unsuccessful or an error occurs while fetching data. """ username = os.environ.get("OSS_USERNAME", None) token = os.environ.get("OSS_TOKEN", None) @@ -91,7 +92,7 @@ def supported_ecosystem(cls): def parse_advisory(component, purl) -> Iterable[VendorData]: """ - Parse component from OSS Index API and yield VendorData. + Parse component from the Sonatype Guide OSS Index compatibility API and yield VendorData. Parameters: component: A list containing a dictionary with component details. diff --git a/vulntotal/tests/test_oss_index.py b/vulntotal/tests/test_oss_index.py index 6ba02e634..6fb9f8083 100644 --- a/vulntotal/tests/test_oss_index.py +++ b/vulntotal/tests/test_oss_index.py @@ -9,6 +9,7 @@ import json from pathlib import Path +from unittest.mock import patch from commoncode import testcase from packageurl import PackageURL @@ -20,6 +21,41 @@ class TestDeps(testcase.FileBasedTesting): test_data_dir = str(Path(__file__).resolve().parent / "test_data" / "oss_index") + def test_fetch_json_response_uses_sonatype_guide_compatibility_api(self): + coordinates = ["pkg:pypi/django@5.2.1"] + datasource = oss_index.OSSDataSource() + + with patch.object(oss_index.requests, "post") as mock_post: + mock_response = mock_post.return_value + mock_response.raise_for_status.return_value = None + mock_response.json.return_value = [] + + assert datasource.fetch_json_response(coordinates) == [] + + mock_post.assert_called_once_with( + "https://api.guide.sonatype.com/api/v3/component-report", + auth=None, + json={"coordinates": coordinates}, + ) + + def test_fetch_json_response_uses_authenticated_sonatype_guide_compatibility_api(self): + coordinates = ["pkg:pypi/django@5.2.1"] + datasource = oss_index.OSSDataSource() + + with patch.dict(oss_index.os.environ, {"OSS_USERNAME": "user", "OSS_TOKEN": "token"}): + with patch.object(oss_index.requests, "post") as mock_post: + mock_response = mock_post.return_value + mock_response.raise_for_status.return_value = None + mock_response.json.return_value = [] + + assert datasource.fetch_json_response(coordinates) == [] + + mock_post.assert_called_once_with( + "https://api.guide.sonatype.com/api/v3/authorized/component-report", + auth=("user", "token"), + json={"coordinates": coordinates}, + ) + def test_parse_advisory(self): advisory_file = self.get_test_loc("advisory.json") with open(advisory_file) as f: