Skip to content

Commit 0bb18b5

Browse files
committed
Add V2 Importer for Tuxcare
Signed-off-by: Sampurna Pyne <sampurnapyne1710@gmail.com>
1 parent 4171dbe commit 0bb18b5

File tree

5 files changed

+318
-0
lines changed

5 files changed

+318
-0
lines changed

vulnerabilities/importers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
from vulnerabilities.pipelines.v2_importers import ruby_importer as ruby_importer_v2
6666
from vulnerabilities.pipelines.v2_importers import vulnrichment_importer as vulnrichment_importer_v2
6767
from vulnerabilities.pipelines.v2_importers import xen_importer as xen_importer_v2
68+
from vulnerabilities.pipelines.v2_importers import tuxcare_importer as tuxcare_importer_v2
6869
from vulnerabilities.utils import create_registry
6970

7071
IMPORTERS_REGISTRY = create_registry(
@@ -90,6 +91,7 @@
9091
ruby_importer_v2.RubyImporterPipeline,
9192
epss_importer_v2.EPSSImporterPipeline,
9293
mattermost_importer_v2.MattermostImporterPipeline,
94+
tuxcare_importer_v2.TuxCareImporterPipeline,
9395
nvd_importer.NVDImporterPipeline,
9496
github_importer.GitHubAPIImporterPipeline,
9597
gitlab_importer.GitLabImporterPipeline,
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import json
2+
import logging
3+
from typing import Iterable
4+
5+
from dateutil import parser as date_parser
6+
from django.utils import timezone
7+
from packageurl import PackageURL
8+
from univers.version_range import GenericVersionRange
9+
10+
from vulnerabilities.importer import AdvisoryData
11+
from vulnerabilities.importer import AffectedPackageV2
12+
from vulnerabilities.importer import ReferenceV2
13+
from vulnerabilities.importer import VulnerabilitySeverity
14+
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2
15+
from vulnerabilities.severity_systems import GENERIC
16+
from vulnerabilities.utils import fetch_response
17+
18+
logger = logging.getLogger(__name__)
19+
20+
21+
class TuxCareImporterPipeline(VulnerableCodeBaseImporterPipelineV2):
22+
pipeline_id = "tuxcare_importer_v2"
23+
spdx_license_expression = "Apache-2.0"
24+
license_url = "https://tuxcare.com/legal"
25+
url = "https://cve.tuxcare.com/els/download-json?orderBy=updated-desc"
26+
27+
@classmethod
28+
def steps(cls):
29+
return (cls.collect_and_store_advisories,)
30+
31+
def advisories_count(self) -> int:
32+
response = fetch_response(self.url)
33+
data = response.json() if response else []
34+
return len(data)
35+
36+
def collect_advisories(self) -> Iterable[AdvisoryData]:
37+
response = fetch_response(self.url)
38+
if not response:
39+
return
40+
41+
data = response.json()
42+
if not data:
43+
return
44+
45+
for record in data:
46+
cve_id = record.get("cve", "").strip()
47+
if not cve_id or not cve_id.startswith("CVE-"):
48+
continue
49+
50+
os_name = record.get("os_name", "").strip()
51+
project_name = record.get("project_name", "").strip()
52+
version = record.get("version", "").strip()
53+
score = record.get("score", "").strip()
54+
severity = record.get("severity", "").strip()
55+
status = record.get("status", "").strip()
56+
last_updated = record.get("last_updated", "").strip()
57+
58+
safe_os = os_name.replace(" ", "_") if os_name else "unknown"
59+
advisory_id = f"TUXCARE-{cve_id}-{safe_os}-{project_name}"
60+
61+
summary = f"TuxCare advisory for {cve_id}"
62+
if project_name:
63+
summary += f" in {project_name}"
64+
if os_name:
65+
summary += f" on {os_name}"
66+
67+
affected_packages = []
68+
if project_name:
69+
purl = PackageURL(type="generic", name=project_name)
70+
71+
affected_version_range = None
72+
if version:
73+
try:
74+
affected_version_range = GenericVersionRange.from_versions([version])
75+
except Exception:
76+
pass
77+
78+
affected_packages.append(
79+
AffectedPackageV2(
80+
package=purl,
81+
affected_version_range=affected_version_range,
82+
)
83+
)
84+
85+
severities = []
86+
if severity and score:
87+
severities.append(
88+
VulnerabilitySeverity(
89+
system=GENERIC,
90+
value=f"{severity} ({score})",
91+
scoring_elements=f"score={score},severity={severity}",
92+
)
93+
)
94+
95+
date_published = None
96+
if last_updated:
97+
try:
98+
date_published = date_parser.parse(last_updated)
99+
if timezone.is_naive(date_published):
100+
date_published = timezone.make_aware(date_published, timezone=timezone.utc)
101+
except Exception:
102+
pass
103+
104+
yield AdvisoryData(
105+
advisory_id=advisory_id,
106+
aliases=[cve_id],
107+
summary=summary,
108+
affected_packages=affected_packages,
109+
references_v2=[ReferenceV2(url="https://cve.tuxcare.com/")],
110+
severities=severities,
111+
date_published=date_published,
112+
url="https://cve.tuxcare.com/",
113+
original_advisory_text=json.dumps(record, indent=2, ensure_ascii=False),
114+
)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
import json
11+
from pathlib import Path
12+
from unittest import TestCase
13+
from unittest.mock import Mock
14+
from unittest.mock import patch
15+
16+
from vulnerabilities.pipelines.v2_importers.tuxcare_importer import TuxCareImporterPipeline
17+
from vulnerabilities.tests import util_tests
18+
19+
TEST_DATA = Path(__file__).parent.parent.parent / "test_data" / "tuxcare"
20+
21+
22+
class TestTuxCareImporterPipeline(TestCase):
23+
@patch("vulnerabilities.pipelines.v2_importers.tuxcare_importer.fetch_response")
24+
def test_collect_advisories(self, mock_fetch):
25+
"""Test collecting and parsing advisories from test data"""
26+
sample_path = TEST_DATA / "data.json"
27+
sample_data = json.loads(sample_path.read_text(encoding="utf-8"))
28+
29+
mock_fetch.return_value = Mock(json=lambda: sample_data)
30+
31+
pipeline = TuxCareImporterPipeline()
32+
advisories = [data.to_dict() for data in list(pipeline.collect_advisories())]
33+
34+
expected_file = TEST_DATA / "expected.json"
35+
util_tests.check_results_against_json(advisories, expected_file)
36+
37+
@patch("vulnerabilities.pipelines.v2_importers.tuxcare_importer.fetch_response")
38+
def test_advisories_count(self, mock_fetch):
39+
"""Test counting advisories"""
40+
sample_path = TEST_DATA / "data.json"
41+
sample_data = json.loads(sample_path.read_text(encoding="utf-8"))
42+
43+
mock_fetch.return_value = Mock(json=lambda: sample_data)
44+
45+
pipeline = TuxCareImporterPipeline()
46+
count = pipeline.advisories_count()
47+
48+
assert count == 5
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
[
2+
{
3+
"cve": "CVE-2023-52922",
4+
"os_name": "CloudLinux 7 ELS",
5+
"project_name": "squid",
6+
"version": "3.5.20",
7+
"score": "7.8",
8+
"severity": "HIGH",
9+
"status": "In Testing",
10+
"last_updated": "2025-12-23 10:08:36.423446"
11+
},
12+
{
13+
"cve": "CVE-2023-52922",
14+
"os_name": "Oracle Linux 7 ELS",
15+
"project_name": "squid",
16+
"version": "3.5.20",
17+
"score": "7.8",
18+
"severity": "HIGH",
19+
"status": "In Testing",
20+
"last_updated": "2025-12-23 10:08:35.944749"
21+
},
22+
{
23+
"cve": "CVE-2023-48161",
24+
"os_name": "RHEL 7 ELS",
25+
"project_name": "java-11-openjdk",
26+
"version": "11.0.23",
27+
"score": "7.1",
28+
"severity": "HIGH",
29+
"status": "In Progress",
30+
"last_updated": "2025-12-23 08:55:12.096092"
31+
},
32+
{
33+
"cve": "CVE-2024-21147",
34+
"os_name": "RHEL 7 ELS",
35+
"project_name": "java-11-openjdk",
36+
"version": "11.0.23",
37+
"score": "7.4",
38+
"severity": "HIGH",
39+
"status": "In Progress",
40+
"last_updated": "2025-12-23 08:55:07.139188"
41+
},
42+
{
43+
"cve": "CVE-2025-21587",
44+
"os_name": "RHEL 7 ELS",
45+
"project_name": "java-11-openjdk",
46+
"version": "11.0.23",
47+
"score": "7.4",
48+
"severity": "HIGH",
49+
"status": "In Progress",
50+
"last_updated": "2025-12-23 08:55:06.706873"
51+
}
52+
]
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
[
2+
{
3+
"advisory_id": "TUXCARE-CVE-2023-52922-CloudLinux_7_ELS-squid",
4+
"aliases": ["CVE-2023-52922"],
5+
"summary": "TuxCare advisory for CVE-2023-52922 in squid on CloudLinux 7 ELS",
6+
"affected_packages": [
7+
{
8+
"package": {"type": "generic", "namespace": "", "name": "squid", "version": "", "qualifiers": "", "subpath": ""},
9+
"affected_version_range": "vers:generic/3.5.20",
10+
"fixed_version_range": null,
11+
"introduced_by_commit_patches": [],
12+
"fixed_by_commit_patches": []
13+
}
14+
],
15+
"references_v2": [{"reference_id": "", "reference_type": "", "url": "https://cve.tuxcare.com/"}],
16+
"patches": [],
17+
"severities": [{"system": "generic_textual", "value": "HIGH (7.8)", "scoring_elements": "score=7.8,severity=HIGH"}],
18+
"date_published": "2025-12-23T10:08:36.423446+00:00",
19+
"weaknesses": [],
20+
"url": "https://cve.tuxcare.com/"
21+
},
22+
{
23+
"advisory_id": "TUXCARE-CVE-2023-52922-Oracle_Linux_7_ELS-squid",
24+
"aliases": ["CVE-2023-52922"],
25+
"summary": "TuxCare advisory for CVE-2023-52922 in squid on Oracle Linux 7 ELS",
26+
"affected_packages": [
27+
{
28+
"package": {"type": "generic", "namespace": "", "name": "squid", "version": "", "qualifiers": "", "subpath": ""},
29+
"affected_version_range": "vers:generic/3.5.20",
30+
"fixed_version_range": null,
31+
"introduced_by_commit_patches": [],
32+
"fixed_by_commit_patches": []
33+
}
34+
],
35+
"references_v2": [{"reference_id": "", "reference_type": "", "url": "https://cve.tuxcare.com/"}],
36+
"patches": [],
37+
"severities": [{"system": "generic_textual", "value": "HIGH (7.8)", "scoring_elements": "score=7.8,severity=HIGH"}],
38+
"date_published": "2025-12-23T10:08:35.944749+00:00",
39+
"weaknesses": [],
40+
"url": "https://cve.tuxcare.com/"
41+
},
42+
{
43+
"advisory_id": "TUXCARE-CVE-2023-48161-RHEL_7_ELS-java-11-openjdk",
44+
"aliases": ["CVE-2023-48161"],
45+
"summary": "TuxCare advisory for CVE-2023-48161 in java-11-openjdk on RHEL 7 ELS",
46+
"affected_packages": [
47+
{
48+
"package": {"type": "generic", "namespace": "", "name": "java-11-openjdk", "version": "", "qualifiers": "", "subpath": ""},
49+
"affected_version_range": "vers:generic/11.0.23",
50+
"fixed_version_range": null,
51+
"introduced_by_commit_patches": [],
52+
"fixed_by_commit_patches": []
53+
}
54+
],
55+
"references_v2": [{"reference_id": "", "reference_type": "", "url": "https://cve.tuxcare.com/"}],
56+
"patches": [],
57+
"severities": [{"system": "generic_textual", "value": "HIGH (7.1)", "scoring_elements": "score=7.1,severity=HIGH"}],
58+
"date_published": "2025-12-23T08:55:12.096092+00:00",
59+
"weaknesses": [],
60+
"url": "https://cve.tuxcare.com/"
61+
},
62+
{
63+
"advisory_id": "TUXCARE-CVE-2024-21147-RHEL_7_ELS-java-11-openjdk",
64+
"aliases": ["CVE-2024-21147"],
65+
"summary": "TuxCare advisory for CVE-2024-21147 in java-11-openjdk on RHEL 7 ELS",
66+
"affected_packages": [
67+
{
68+
"package": {"type": "generic", "namespace": "", "name": "java-11-openjdk", "version": "", "qualifiers": "", "subpath": ""},
69+
"affected_version_range": "vers:generic/11.0.23",
70+
"fixed_version_range": null,
71+
"introduced_by_commit_patches": [],
72+
"fixed_by_commit_patches": []
73+
}
74+
],
75+
"references_v2": [{"reference_id": "", "reference_type": "", "url": "https://cve.tuxcare.com/"}],
76+
"patches": [],
77+
"severities": [{"system": "generic_textual", "value": "HIGH (7.4)", "scoring_elements": "score=7.4,severity=HIGH"}],
78+
"date_published": "2025-12-23T08:55:07.139188+00:00",
79+
"weaknesses": [],
80+
"url": "https://cve.tuxcare.com/"
81+
},
82+
{
83+
"advisory_id": "TUXCARE-CVE-2025-21587-RHEL_7_ELS-java-11-openjdk",
84+
"aliases": ["CVE-2025-21587"],
85+
"summary": "TuxCare advisory for CVE-2025-21587 in java-11-openjdk on RHEL 7 ELS",
86+
"affected_packages": [
87+
{
88+
"package": {"type": "generic", "namespace": "", "name": "java-11-openjdk", "version": "", "qualifiers": "", "subpath": ""},
89+
"affected_version_range": "vers:generic/11.0.23",
90+
"fixed_version_range": null,
91+
"introduced_by_commit_patches": [],
92+
"fixed_by_commit_patches": []
93+
}
94+
],
95+
"references_v2": [{"reference_id": "", "reference_type": "", "url": "https://cve.tuxcare.com/"}],
96+
"patches": [],
97+
"severities": [{"system": "generic_textual", "value": "HIGH (7.4)", "scoring_elements": "score=7.4,severity=HIGH"}],
98+
"date_published": "2025-12-23T08:55:06.706873+00:00",
99+
"weaknesses": [],
100+
"url": "https://cve.tuxcare.com/"
101+
}
102+
]

0 commit comments

Comments
 (0)