Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions vulnerabilities/importers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from vulnerabilities.pipelines.v2_importers import collect_fix_commits as collect_fix_commits_v2
from vulnerabilities.pipelines.v2_importers import curl_importer as curl_importer_v2
from vulnerabilities.pipelines.v2_importers import debian_importer as debian_importer_v2
from vulnerabilities.pipelines.v2_importers import eclipse_importer as eclipse_importer_v2
from vulnerabilities.pipelines.v2_importers import (
elixir_security_importer as elixir_security_importer_v2,
)
Expand Down Expand Up @@ -99,6 +100,7 @@
xen_importer_v2.XenImporterPipeline,
curl_importer_v2.CurlImporterPipeline,
oss_fuzz_v2.OSSFuzzImporterPipeline,
eclipse_importer_v2.EclipseImporterPipeline,
istio_importer_v2.IstioImporterPipeline,
postgresql_importer_v2.PostgreSQLImporterPipeline,
mozilla_importer_v2.MozillaImporterPipeline,
Expand Down
102 changes: 102 additions & 0 deletions vulnerabilities/pipelines/v2_importers/eclipse_importer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#
# 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 json
import logging
from typing import Iterable

import dateparser
import requests

from vulnerabilities.importer import AdvisoryDataV2
from vulnerabilities.importer import ReferenceV2
from vulnerabilities.importer import VulnerabilitySeverity
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2
from vulnerabilities.severity_systems import GENERIC

logger = logging.getLogger(__name__)

ECLIPSE_API_URL = "https://api.eclipse.org/cve"


class EclipseImporterPipeline(VulnerableCodeBaseImporterPipelineV2):
"""Collect Eclipse Foundation security advisories via the Eclipse CVE API."""

pipeline_id = "eclipse_importer"
spdx_license_expression = "LicenseRef-scancode-proprietary-license"
license_url = "https://www.eclipse.org/security/"
precedence = 200

@classmethod
def steps(cls):
return (
cls.fetch,
cls.collect_and_store_advisories,
)

def fetch(self):
self.log(f"Fetch `{ECLIPSE_API_URL}`")
resp = requests.get(ECLIPSE_API_URL, timeout=30)
resp.raise_for_status()
self.advisories_data = resp.json()

def advisories_count(self):
return len(self.advisories_data)

def collect_advisories(self) -> Iterable[AdvisoryDataV2]:
for entry in self.advisories_data:
advisory = parse_advisory(entry)
if advisory:
yield advisory


def parse_advisory(entry: dict):
advisory_id = entry.get("id") or ""

date_published = None
raw_date = entry.get("date_published") or ""
if raw_date:
date_published = dateparser.parse(
raw_date,
settings={"TIMEZONE": "UTC", "RETURN_AS_TIMEZONE_AWARE": True, "TO_TIMEZONE": "UTC"},
)
if date_published is None:
logger.warning("Could not parse date %r for %s", raw_date, advisory_id)

summary_obj = entry.get("summary") or {}
summary = summary_obj.get("content") or ""

references = []
for url in [
entry.get("live_link") or "",
entry.get("request_link") or "",
entry.get("cve_pull_request") or "",
]:
if url:
references.append(ReferenceV2(url=url))

severities = []
cvss = entry.get("cvss")
if cvss:
severities.append(VulnerabilitySeverity(system=GENERIC, value=str(cvss)))

advisory_url = entry.get("live_link") or ""

return AdvisoryDataV2(
advisory_id=advisory_id,
aliases=[],
summary=summary,
affected_packages=[],
references=references,
date_published=date_published,
weaknesses=[],
severities=severities,
url=advisory_url,
original_advisory_text=json.dumps(entry, indent=2, ensure_ascii=False),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#
# 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 import TestCase
from unittest.mock import MagicMock
from unittest.mock import patch

from vulnerabilities.pipelines.v2_importers.eclipse_importer import EclipseImporterPipeline
from vulnerabilities.pipelines.v2_importers.eclipse_importer import parse_advisory
from vulnerabilities.tests import util_tests
from vulnerabilities.utils import load_json

TEST_DATA = Path(__file__).parent.parent.parent / "test_data" / "eclipse"

SAMPLE_DATA = load_json(TEST_DATA / "eclipse_api_sample.json")


def test_parse_advisories():
results = [parse_advisory(entry).to_dict() for entry in SAMPLE_DATA]
expected_file = TEST_DATA / "expected_eclipse_output.json"
util_tests.check_results_against_json(results, expected_file)


class TestEclipseImporterPipeline(TestCase):
def setUp(self):
self.pipeline = EclipseImporterPipeline()
self.pipeline.advisories_data = SAMPLE_DATA

def test_advisories_count(self):
assert self.pipeline.advisories_count() == 3

def test_collect_advisories_yields_all_valid(self):
advisories = list(self.pipeline.collect_advisories())
assert len(advisories) == 3

@patch("vulnerabilities.pipelines.v2_importers.eclipse_importer.requests.get")
def test_fetch_stores_advisories_data(self, mock_get):
mock_resp = MagicMock()
mock_resp.json.return_value = SAMPLE_DATA
mock_get.return_value = mock_resp
self.pipeline.fetch()
assert self.pipeline.advisories_data == SAMPLE_DATA
41 changes: 41 additions & 0 deletions vulnerabilities/tests/test_data/eclipse/eclipse_api_sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[
{
"id": "CVE-2017-7649",
"date_published": "2017-04-14",
"project": "iot.kura",
"request_link": "https://bugs.eclipse.org/bugs/show_bug.cgi?id=514681",
"cve_pull_request": "",
"status": "PUBLIC",
"summary": {
"content": "The network enabled distribution of Kura before 2.1.0 takes control over the device's firewall...",
"source": "https://api.github.com/advisories?cve_id=CVE-2017-7649"
},
"cvss": 9.8,
"live_link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7649"
},
{
"id": "CVE-2018-12537",
"date_published": "2018-06-19",
"project": "rt.vertx",
"request_link": "https://bugs.eclipse.org/bugs/show_bug.cgi?id=536038",
"cve_pull_request": "https://github.com/CVEProject/cvelist/pull/932",
"status": "PUBLIC",
"summary": {
"content": "Moderate severity vulnerability that affects io.vertx:vertx-core",
"source": "https://api.github.com/advisories?cve_id=CVE-2018-12537"
},
"cvss": null,
"live_link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12537"
},
{
"id": "CVE-2024-2212",
"date_published": "2024-03-06",
"project": "iot.threadx",
"request_link": "https://github.com/eclipse-threadx/threadx/security/advisories/GHSA-v9jj-7qjg-h6g6",
"cve_pull_request": "",
"status": "PUBLIC",
"summary": null,
"cvss": null,
"live_link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-2212"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
[
{
"advisory_id": "CVE-2017-7649",
"aliases": [],
"summary": "The network enabled distribution of Kura before 2.1.0 takes control over the device's firewall...",
"affected_packages": [],
"references": [
{
"reference_id": "",
"reference_type": "",
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7649"
},
{
"reference_id": "",
"reference_type": "",
"url": "https://bugs.eclipse.org/bugs/show_bug.cgi?id=514681"
}
],
"patches": [],
"severities": [
{
"system": "generic_textual",
"value": "9.8",
"scoring_elements": ""
}
],
"date_published": "2017-04-14T00:00:00+00:00",
"weaknesses": [],
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7649"
},
{
"advisory_id": "CVE-2018-12537",
"aliases": [],
"summary": "Moderate severity vulnerability that affects io.vertx:vertx-core",
"affected_packages": [],
"references": [
{
"reference_id": "",
"reference_type": "",
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12537"
},
{
"reference_id": "",
"reference_type": "",
"url": "https://bugs.eclipse.org/bugs/show_bug.cgi?id=536038"
},
{
"reference_id": "",
"reference_type": "",
"url": "https://github.com/CVEProject/cvelist/pull/932"
}
],
"patches": [],
"severities": [],
"date_published": "2018-06-19T00:00:00+00:00",
"weaknesses": [],
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12537"
},
{
"advisory_id": "CVE-2024-2212",
"aliases": [],
"summary": "",
"affected_packages": [],
"references": [
{
"reference_id": "",
"reference_type": "",
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-2212"
},
{
"reference_id": "",
"reference_type": "",
"url": "https://github.com/eclipse-threadx/threadx/security/advisories/GHSA-v9jj-7qjg-h6g6"
}
],
"patches": [],
"severities": [],
"date_published": "2024-03-06T00:00:00+00:00",
"weaknesses": [],
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-2212"
}
]