Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import data from OpenSSF Malicious Packages #1412

Closed
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 @@ -24,6 +24,7 @@
from vulnerabilities.importers import nginx
from vulnerabilities.importers import npm
from vulnerabilities.importers import nvd
from vulnerabilities.importers import openssf
from vulnerabilities.importers import openssl
from vulnerabilities.importers import oss_fuzz
from vulnerabilities.importers import postgresql
Expand Down Expand Up @@ -67,6 +68,7 @@
fireeye.FireyeImporter,
apache_kafka.ApacheKafkaImporter,
oss_fuzz.OSSFuzzImporter,
openssf.OpenSSFImporter,
]

IMPORTERS_REGISTRY = {x.qualified_name: x for x in IMPORTERS_REGISTRY}
55 changes: 55 additions & 0 deletions vulnerabilities/importers/openssf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#
# 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/nexB/vulnerablecode for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
import json
import logging
from pathlib import Path
from typing import Iterable

from vulnerabilities.importer import AdvisoryData
from vulnerabilities.importer import Importer
from vulnerabilities.importers.osv import parse_advisory_data
from vulnerabilities.utils import get_advisory_url

logger = logging.getLogger(__name__)


class OpenSSFImporter(Importer):
license_url = "https://github.com/ossf/malicious-packages/blob/main/LICENSE"
spdx_license_expression = "CC-BY-4.0"
url = "git+https://github.com/ossf/malicious-packages"
importer_name = "OpenSSF Malacious Packages Importer"

def advisory_data(self) -> Iterable[AdvisoryData]:
try:
supported_ecosystems = ["crates.io", "npm", "pypi", "rubygems"]
self.clone(repo_url=self.url)
base_path = Path(self.vcs_response.dest_dir)

for supported_ecosystem in supported_ecosystems:
path = base_path / "osv" / "malicious" / supported_ecosystem

for file in path.glob("**/*.json"):
try:
with open(file) as f:
json_data = json.load(f)
advisory_url = get_advisory_url(
file=file,
base_path=base_path,
url="https://github.com/ossf/malicious-packages/blob/main",
)
yield parse_advisory_data(
json_data,
supported_ecosystem=supported_ecosystem,
advisory_url=advisory_url,
)
except Exception as e:
logger.debug(f"Filepath {file} threw an Exception {type(e).__name__} {e!r}")
finally:
if self.vcs_response:
self.vcs_response.delete()
1 change: 1 addition & 0 deletions vulnerabilities/improvers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
valid_versions.DebianOvalImprover,
valid_versions.UbuntuOvalImprover,
valid_versions.OSSFuzzImprover,
valid_versions.OpenSSFImprover,
vulnerability_status.VulnerabilityStatusImprover,
]

Expand Down
6 changes: 6 additions & 0 deletions vulnerabilities/improvers/valid_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from vulnerabilities.importers.istio import IstioImporter
from vulnerabilities.importers.nginx import NginxImporter
from vulnerabilities.importers.npm import NpmImporter
from vulnerabilities.importers.openssf import OpenSSFImporter
from vulnerabilities.importers.oss_fuzz import OSSFuzzImporter
from vulnerabilities.importers.ubuntu import UbuntuImporter
from vulnerabilities.improver import MAX_CONFIDENCE
Expand Down Expand Up @@ -460,3 +461,8 @@ class UbuntuOvalImprover(ValidVersionImprover):
class OSSFuzzImprover(ValidVersionImprover):
importer = OSSFuzzImporter
ignorable_versions = []


class OpenSSFImprover(ValidVersionImprover):
importer = OpenSSFImporter
ignorable_versions = []
43 changes: 43 additions & 0 deletions vulnerabilities/tests/test_data/openssf/openssf-data1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"modified": "2023-07-19T06:30:24Z",
"published": "2023-07-19T06:30:24Z",
"schema_version": "1.5.0",
"id": "MAL-2023-1426",
"summary": "Malicious code in google-apis-androidpublisher_v2 (RubyGems)",
"details": "\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: ossf-package-analysis (715b9e91530380e15e848bc0374f342584cdd61853308582683eb214e0da9927)\nThe OpenSSF Package Analysis project identified 'google-apis-androidpublisher_v2' @ 0.0 (rubygems) as malicious.\n\nIt is considered malicious because:\n- The package communicates with a domain associated with malicious activity.\n",
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "google-apis-androidpublisher_v2"
},
"versions": [
"0.0"
]
}
],
"credits": [
{
"name": "OpenSSF: Package Analysis",
"type": "FINDER",
"contact": [
"https://github.com/ossf/package-analysis",
"https://openssf.slack.com/channels/package_analysis"
]
}
],
"database_specific": {
"malicious-packages-origins": [
{
"import_time": "2023-08-10T06:16:36.932649705Z",
"modified_time": "2023-07-19T06:30:24.337173817Z",
"sha256": "715b9e91530380e15e848bc0374f342584cdd61853308582683eb214e0da9927",
"source": "ossf-package-analysis",
"versions": [
"0.0"
]
}
]
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"aliases": ["MAL-2023-1426"],
"summary": "Malicious code in google-apis-androidpublisher_v2 (RubyGems)\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: ossf-package-analysis (715b9e91530380e15e848bc0374f342584cdd61853308582683eb214e0da9927)\nThe OpenSSF Package Analysis project identified 'google-apis-androidpublisher_v2' @ 0.0 (rubygems) as malicious.\n\nIt is considered malicious because:\n- The package communicates with a domain associated with malicious activity.",
"affected_packages": [],
"references": [],
"date_published": "2023-07-19T06:30:24+00:00",
"weaknesses": [],
"url": "http://test.com"
}
43 changes: 43 additions & 0 deletions vulnerabilities/tests/test_data/openssf/openssf-data2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"modified": "2023-07-12T14:53:05Z",
"published": "2023-07-12T14:53:05Z",
"schema_version": "1.5.0",
"id": "MAL-2023-1077",
"summary": "Malicious code in 1password-postman-integration (npm)",
"details": "\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: ossf-package-analysis (93be26c7bf7ce939a783f5c98c26ecd585430bdb1c993cf3f78dd213a316a058)\nThe OpenSSF Package Analysis project identified '1password-postman-integration' @ 1.0.0 (npm) as malicious.\n\nIt is considered malicious because:\n- The package communicates with a domain associated with malicious activity.\n",
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "1password-postman-integration"
},
"versions": [
"1.0.0"
]
}
],
"credits": [
{
"name": "OpenSSF: Package Analysis",
"type": "FINDER",
"contact": [
"https://github.com/ossf/package-analysis",
"https://openssf.slack.com/channels/package_analysis"
]
}
],
"database_specific": {
"malicious-packages-origins": [
{
"import_time": "2023-08-10T06:16:31.337614734Z",
"modified_time": "2023-07-12T14:53:05.954866979Z",
"sha256": "93be26c7bf7ce939a783f5c98c26ecd585430bdb1c993cf3f78dd213a316a058",
"source": "ossf-package-analysis",
"versions": [
"1.0.0"
]
}
]
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"aliases": ["MAL-2023-1077"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be used as an alias? What other options we have?

cc @pombredanne

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TG1999 yes, as an alias sounds fine

"summary": "Malicious code in 1password-postman-integration (npm)\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: ossf-package-analysis (93be26c7bf7ce939a783f5c98c26ecd585430bdb1c993cf3f78dd213a316a058)\nThe OpenSSF Package Analysis project identified '1password-postman-integration' @ 1.0.0 (npm) as malicious.\n\nIt is considered malicious because:\n- The package communicates with a domain associated with malicious activity.",
"affected_packages": [],
"references": [],
"date_published": "2023-07-12T14:53:05+00:00",
"weaknesses": [],
"url": "http://test.com"
}
39 changes: 39 additions & 0 deletions vulnerabilities/tests/test_openssf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# 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/nexB/vulnerablecode for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
import json
import os
from unittest import TestCase

from vulnerabilities.importers.osv import parse_advisory_data
from vulnerabilities.tests import util_tests

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
TEST_DATA = os.path.join(BASE_DIR, "test_data/openssf")


class TestOpenSSFImporter(TestCase):
def test_to_advisories1(self):
with open(os.path.join(TEST_DATA, "openssf-data1.json")) as f:
mock_response = json.load(f)
expected_file = os.path.join(TEST_DATA, "openssf-data1.json-expected.json")
imported_data = parse_advisory_data(
mock_response, "openssf", advisory_url="http://test.com"
)
result = imported_data.to_dict()
util_tests.check_results_against_json(result, expected_file)

def test_to_advisories2(self):
with open(os.path.join(TEST_DATA, "openssf-data2.json")) as f:
mock_response = json.load(f)
expected_file = os.path.join(TEST_DATA, "openssf-data2.json-expected.json")
imported_data = parse_advisory_data(
mock_response, "openssf", advisory_url="http://test.com"
)
result = imported_data.to_dict()
util_tests.check_results_against_json(result, expected_file)
Loading