diff --git a/vulnerabilities/templatetags/__init__.py b/vulnerabilities/templatetags/__init__.py
new file mode 100644
index 000000000..bdac1cd30
--- /dev/null
+++ b/vulnerabilities/templatetags/__init__.py
@@ -0,0 +1,8 @@
+#
+# 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.
+#
diff --git a/vulnerabilities/templatetags/show_cvss.py b/vulnerabilities/templatetags/show_cvss.py
new file mode 100644
index 000000000..52533d0f2
--- /dev/null
+++ b/vulnerabilities/templatetags/show_cvss.py
@@ -0,0 +1,17 @@
+from django import template
+from django.utils.safestring import mark_safe
+
+register = template.Library()
+
+
+@register.filter(is_safe=True)
+def cvss_printer(selected_vector, vector_values):
+ """highlight the selected vector value and return a list of paragraphs"""
+ p_list = []
+ selected_vector = selected_vector.lower()
+ for vector_value in vector_values.split(","):
+ if selected_vector == vector_value:
+ p_list.append(f"
{selected_vector}
")
+ else:
+ p_list.append(f"
{vector_value}
")
+ return mark_safe("".join(p_list))
diff --git a/vulnerabilities/tests/conftest.py b/vulnerabilities/tests/conftest.py
index 8076f4b9b..f9216c742 100644
--- a/vulnerabilities/tests/conftest.py
+++ b/vulnerabilities/tests/conftest.py
@@ -26,7 +26,6 @@ def no_rmtree(monkeypatch):
# Step 3: Migrate all the tests
collect_ignore = [
"test_models.py",
- "test_ruby.py",
"test_rust.py",
"test_suse_backports.py",
"test_suse.py",
diff --git a/vulnerabilities/tests/test_api.py b/vulnerabilities/tests/test_api.py
index f94fe80cb..197707a01 100644
--- a/vulnerabilities/tests/test_api.py
+++ b/vulnerabilities/tests/test_api.py
@@ -9,6 +9,7 @@
import json
import os
+from collections import OrderedDict
from urllib.parse import quote
from django.test import TestCase
@@ -223,18 +224,21 @@ def test_api_with_single_vulnerability(self):
"vulnerability_id": self.vulnerability.vulnerability_id,
"summary": "test",
"aliases": [],
+ "resource_url": f"http://testserver/vulnerabilities/{self.vulnerability.vulnerability_id}",
"fixed_packages": [
{
"url": f"http://testserver/api/packages/{self.pkg2.id}",
"purl": "pkg:deb/flask@0.1.2",
"is_vulnerable": False,
"affected_by_vulnerabilities": [],
+ "resource_url": f"http://testserver/packages/{self.pkg2.purl}",
},
{
"url": f"http://testserver/api/packages/{self.pkg1.id}",
"purl": "pkg:pypi/flask@0.1.2",
"is_vulnerable": False,
"affected_by_vulnerabilities": [],
+ "resource_url": f"http://testserver/packages/{self.pkg1.purl}",
},
],
"affected_packages": [],
@@ -257,11 +261,13 @@ def test_api_with_single_vulnerability_with_filters(self):
"vulnerability_id": self.vulnerability.vulnerability_id,
"summary": "test",
"aliases": [],
+ "resource_url": f"http://testserver/vulnerabilities/{self.vulnerability.vulnerability_id}",
"fixed_packages": [
{
"url": f"http://testserver/api/packages/{self.pkg1.id}",
"purl": "pkg:pypi/flask@0.1.2",
"is_vulnerable": False,
+ "resource_url": f"http://testserver/packages/{self.pkg1.purl}",
"affected_by_vulnerabilities": [],
},
],
@@ -443,49 +449,106 @@ def test_api_with_lesser_and_greater_fixed_by_packages(self):
"next_non_vulnerable_version": "2.14.0-rc1",
"latest_non_vulnerable_version": "2.14.0-rc1",
"affected_by_vulnerabilities": [
- {
- "url": f"http://testserver/api/vulnerabilities/{self.vuln_VCID_2nyb_8rwu_aaag.id}",
- "vulnerability_id": "VCID-2nyb-8rwu-aaag",
- "summary": "This is VCID-2nyb-8rwu-aaag",
- "references": [],
- "fixed_packages": [
- {
- "url": f"http://testserver/api/packages/{self.package_maven_jackson_databind_2_13_2.id}",
- "purl": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.2",
- "is_vulnerable": True,
- "affected_by_vulnerabilities": [
- {"vulnerability": "VCID-gqhw-ngh8-aaap"}
+ OrderedDict(
+ [
+ (
+ "url",
+ f"http://testserver/api/vulnerabilities/{self.vuln_VCID_2nyb_8rwu_aaag.id}",
+ ),
+ ("vulnerability_id", "VCID-2nyb-8rwu-aaag"),
+ ("summary", "This is VCID-2nyb-8rwu-aaag"),
+ ("references", []),
+ (
+ "fixed_packages",
+ [
+ OrderedDict(
+ [
+ (
+ "url",
+ f"http://testserver/api/packages/{self.package_maven_jackson_databind_2_13_2.id}",
+ ),
+ (
+ "purl",
+ "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.2",
+ ),
+ ("is_vulnerable", True),
+ (
+ "affected_by_vulnerabilities",
+ [{"vulnerability": "VCID-gqhw-ngh8-aaap"}],
+ ),
+ (
+ "resource_url",
+ "http://testserver/packages/pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.2",
+ ),
+ ]
+ )
],
- }
- ],
- "aliases": ["CVE-2020-36518", "GHSA-57j2-w4cx-62h2"],
- }
+ ),
+ ("aliases", ["CVE-2020-36518", "GHSA-57j2-w4cx-62h2"]),
+ ("resource_url", "http://testserver/vulnerabilities/VCID-2nyb-8rwu-aaag"),
+ ]
+ )
],
"fixing_vulnerabilities": [
- {
- "url": f"http://testserver/api/vulnerabilities/{self.vuln_VCID_ftmk_wbwx_aaar.id}",
- "vulnerability_id": "VCID-ftmk-wbwx-aaar",
- "summary": "This is VCID-ftmk-wbwx-aaar",
- "references": [],
- "fixed_packages": [
- {
- "url": f"http://testserver/api/packages/{self.package_maven_jackson_databind_2_12_6.id}",
- "purl": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.12.6",
- "is_vulnerable": False,
- "affected_by_vulnerabilities": [],
- },
- {
- "url": f"http://testserver/api/packages/{self.package_maven_jackson_databind_2_13_1.id}",
- "purl": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.1",
- "is_vulnerable": True,
- "affected_by_vulnerabilities": [
- {"vulnerability": "VCID-2nyb-8rwu-aaag"}
+ OrderedDict(
+ [
+ (
+ "url",
+ f"http://testserver/api/vulnerabilities/{self.vuln_VCID_ftmk_wbwx_aaar.id}",
+ ),
+ ("vulnerability_id", "VCID-ftmk-wbwx-aaar"),
+ ("summary", "This is VCID-ftmk-wbwx-aaar"),
+ ("references", []),
+ (
+ "fixed_packages",
+ [
+ OrderedDict(
+ [
+ (
+ "url",
+ f"http://testserver/api/packages/{self.package_maven_jackson_databind_2_12_6.id}",
+ ),
+ (
+ "purl",
+ "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.12.6",
+ ),
+ ("is_vulnerable", False),
+ ("affected_by_vulnerabilities", []),
+ (
+ "resource_url",
+ "http://testserver/packages/pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.12.6",
+ ),
+ ]
+ ),
+ OrderedDict(
+ [
+ (
+ "url",
+ f"http://testserver/api/packages/{self.package_maven_jackson_databind_2_13_1.id}",
+ ),
+ (
+ "purl",
+ "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.1",
+ ),
+ ("is_vulnerable", True),
+ (
+ "affected_by_vulnerabilities",
+ [{"vulnerability": "VCID-2nyb-8rwu-aaag"}],
+ ),
+ (
+ "resource_url",
+ "http://testserver/packages/pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.1",
+ ),
+ ]
+ ),
],
- },
- ],
- "aliases": ["CVE-2021-46877", "GHSA-3x8x-79m2-3w2w"],
- },
+ ),
+ ("aliases", ["CVE-2021-46877", "GHSA-3x8x-79m2-3w2w"]),
+ ("resource_url", "http://testserver/vulnerabilities/VCID-ftmk-wbwx-aaar"),
+ ]
+ )
],
+ "resource_url": "http://testserver/packages/pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.1",
}
assert response == expected_response
diff --git a/vulnerabilities/tests/test_data/fireeye/fireeye_test3.md b/vulnerabilities/tests/test_data/fireeye/fireeye_test3.md
new file mode 100644
index 000000000..b825b967b
--- /dev/null
+++ b/vulnerabilities/tests/test_data/fireeye/fireeye_test3.md
@@ -0,0 +1,31 @@
+# MNDT-2023-0017
+
+The IBM Personal Communications (PCOMM) application 13.0.0 and earlier caused a user's plaintext password to be written to the `C:\Temp\pcsnp_init.log` file when re-connection was made through a remote desktop protocol.
+
+## Common Weakness Enumeration
+CWE-312: Cleartext Storage of Sensitive Information
+
+## Impact
+High - An attacker with low-privilege access to a host with IBM PCOMM could recover the plaintext password of another user.
+
+## Exploitability
+Low - Exploitability varies depending on the environment in which IBM PCOMM is installed. Mandiant identified this vulnerability when conducting independent security research for a client that used Citrix to connect to shared Windows Server instances. In certain environments where remote desktop is used to connect to shared hosts with IBM PCOMM installed, the exploitability is greatly increased.
+
+## CVE Reference
+CVE-2016-0321 - scope expanded
+
+## Technical Details
+While conducting independent security research, Mandiant identified a plaintext Active Directory password stored within the `C:\Temp\pcsnp_init.log` file. The affected host had IBM PCOMM version 13.0.0 installed and was used by multiple users who connected with Citrix. Upon a user connecting, disconnecting, and connecting again, the user's plaintext password was stored in the `C:\Temp\pcsnp_init.log` file.
+
+## Discovery Credits
+- Adin Drabkin, Mandiant
+- Matthew Rotlevi, Mandiant
+
+## Disclosure Timeline
+- 2023-09-26 - Issue reported to the vendor.
+- 2023-11-03 - The vendor updated the security bulletin for CVE-2016-0321 to include all known affected and fixed versions.
+
+## References
+- [IBM Security Bulletin](https://www.ibm.com/support/pages/security-bulletin-ibm-personal-communications-could-allow-remote-user-obtain-sensitive-information-including-user-passwords-allowing-unauthorized-access-cve-2016-0321)
+- [IBM Personal Communications](https://www.ibm.com/support/pages/ibm-personal-communications)
+- [Mitre CVE-2016-0321](https://www.cve.org/CVERecord?id=CVE-2016-0321)
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_expected_1.json b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_1.json
new file mode 100644
index 000000000..2182e5db4
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_1.json
@@ -0,0 +1,122 @@
+{
+ "aliases": [
+ "CVE-2015-8315",
+ "GHSA-3fx5-fwvr-xrjg"
+ ],
+ "summary": "Regular Expression Denial of Service in ms\nVersions of `ms` prior to 0.7.1 are affected by a regular expression denial of service vulnerability when extremely long version strings are parsed.\n\n## Proof of Concept\n```javascript\nvar ms = require('ms');\nvar genstr = function (len, chr) {\n var result = \"\";\n for (i=0; i<=len; i++) {\n result = result + chr;\n }\n\n return result;\n}\n\nms(genstr(process.argv[2], \"5\") + \" minutea\");\n\n```\n\n### Results\nShowing increase in execution time based on the input string.\n```\n$ time node ms.js 10000\n\nreal\t0m0.758s\nuser\t0m0.724s\nsys\t0m0.031s\n\n$ time node ms.js 20000\n\nreal\t0m2.580s\nuser\t0m2.494s\nsys\t0m0.047s\n\n$ time node ms.js 30000\n\nreal\t0m5.747s\nuser\t0m5.483s\nsys\t0m0.080s\n\n$ time node ms.js 80000\n\nreal\t0m41.022s\nuser\t0m38.894s\nsys\t0m0.529s\n```",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "npm",
+ "namespace": null,
+ "name": "ms",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "0.7.1"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2015-8315",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/unshiftio/millisecond/",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://support.f5.com/csp/article/K46337613?utm_source=f5support&utm_medium=RSS",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://www.npmjs.com/advisories/46",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://www.openwall.com/lists/oss-security/2016/04/20/11",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://www.securityfocus.com/bid/96389",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2017-10-24T18:33:36+00:00",
+ "weaknesses": [400],
+ "url": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/github_osv_test_1.json"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_expected_2.json b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_2.json
new file mode 100644
index 000000000..8a23cff27
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_2.json
@@ -0,0 +1,79 @@
+{
+ "aliases": [
+ "CVE-2022-1036",
+ "GHSA-3qr6-qrqm-8v86"
+ ],
+ "summary": "Integer Overflow or Wraparound in Microweber\nIn Microweber prior to 1.2.12, a user can create an account with a password thousands of characters in length, leading to memory corruption/integer overflow. Version 1.2.2 sets maximum password length at 500 characters.",
+ "affected_packages": [
+
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-1036",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/microweber/microweber/commit/82be4f0b4729be870ccefdae99a04833f134aa6a",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/microweber/microweber",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://huntr.dev/bounties/db615581-d5a9-4ca5-a3e9-7a39eceaa424",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2022-03-23T00:00:23+00:00",
+ "weaknesses": [190],
+ "url": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/github_osv_test_2.json"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_expected_3.json b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_3.json
new file mode 100644
index 000000000..7bfc88189
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_3.json
@@ -0,0 +1,142 @@
+{
+ "aliases": [
+ "CVE-2020-10688",
+ "GHSA-29qj-rvv6-qrmv"
+ ],
+ "summary": "Cross-site scripting in RESTEasy\nA cross-site scripting (XSS) flaw was found in RESTEasy in versions before 3.11.1.Final and before 4.5.3.Final, where it did not properly handle URL encoding when the RESTEASY003870 exception occurs. An attacker could use this flaw to launch a reflected XSS attack.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "maven",
+ "namespace": "org.jboss.resteasy",
+ "name": "resteasy-bom",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "3.11.1.Final"
+ },
+ {
+ "package": {
+ "type": "maven",
+ "namespace": "org.jboss.resteasy",
+ "name": "resteasy-bom",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "4.5.3.Final"
+ },
+ {
+ "package": {
+ "type": "maven",
+ "namespace": "org.jboss.resteasy",
+ "name": "resteasy-core",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "3.11.1.Final"
+ },
+ {
+ "package": {
+ "type": "maven",
+ "namespace": "org.jboss.resteasy",
+ "name": "resteasy-core",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "4.5.3.Final"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-10688",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "5.4",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/quarkusio/quarkus/issues/7248",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "5.4",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://bugzilla.redhat.com/show_bug.cgi?id=1814974",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "5.4",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://issues.redhat.com/browse/RESTEASY-2519",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "5.4",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://security.netapp.com/advisory/ntap-20210706-0008/",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "5.4",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2021-06-15T16:05:22+00:00",
+ "weaknesses": [79],
+ "url": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/github_osv_test_3.json"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_expected_4.json b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_4.json
new file mode 100644
index 000000000..a58d9cb0b
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_4.json
@@ -0,0 +1,194 @@
+{
+ "aliases": [
+ "CVE-2011-0447",
+ "GHSA-24fg-p96v-hxh8"
+ ],
+ "summary": "Moderate severity vulnerability that affects rails\nRuby on Rails 2.1.x, 2.2.x, and 2.3.x before 2.3.11, and 3.x before 3.0.4, does not properly validate HTTP requests that contain an X-Requested-With header, which makes it easier for remote attackers to conduct cross-site request forgery (CSRF) attacks via forged (1) AJAX or (2) API requests that leverage \"combinations of browser plugins and HTTP redirects,\" a related issue to CVE-2011-0696.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "gem",
+ "namespace": null,
+ "name": "rails",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "2.3.11"
+ },
+ {
+ "package": {
+ "type": "gem",
+ "namespace": null,
+ "name": "rails",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "3.0.4"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2011-0447",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/advisories/GHSA-24fg-p96v-hxh8",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://groups.google.com/group/rubyonrails-security/msg/c22ea1668c0d181c?dmode=source&output=gplain",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://lists.fedoraproject.org/pipermail/package-announce/2011-April/057650.html",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://lists.fedoraproject.org/pipermail/package-announce/2011-March/055074.html",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://lists.fedoraproject.org/pipermail/package-announce/2011-March/055088.html",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://secunia.com/advisories/43274",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://secunia.com/advisories/43666",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://www.debian.org/security/2011/dsa-2247",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://www.securityfocus.com/bid/46291",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://www.securitytracker.com/id?1025060",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://www.vupen.com/english/advisories/2011/0587",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://www.vupen.com/english/advisories/2011/0877",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2017-10-24T18:33:38+00:00",
+ "weaknesses": [
+ 352
+ ],
+ "url": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/github_osv_test_4.json"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_expected_5.json b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_5.json
new file mode 100644
index 000000000..41718243e
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_5.json
@@ -0,0 +1,224 @@
+{
+ "aliases": [
+ "CVE-2023-2727",
+ "GHSA-qc2g-gmh6-95p4"
+ ],
+ "summary": "kube-apiserver vulnerable to policy bypass\nUsers may be able to launch containers using images that are restricted by ImagePolicyWebhook when using ephemeral containers. Kubernetes clusters are only affected if the ImagePolicyWebhook admission plugin is used together with ephemeral containers.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "golang",
+ "namespace": "k8s.io",
+ "name": "kubernetes",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "1.27.3"
+ },
+ {
+ "package": {
+ "type": "golang",
+ "namespace": "k8s.io",
+ "name": "kubernetes",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "1.26.6"
+ },
+ {
+ "package": {
+ "type": "golang",
+ "namespace": "k8s.io",
+ "name": "kubernetes",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "1.25.11"
+ },
+ {
+ "package": {
+ "type": "golang",
+ "namespace": "k8s.io",
+ "name": "kubernetes",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "1.24.15"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-2727",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/kubernetes/kubernetes/issues/118640",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118356",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118471",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118473",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118474",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118512",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/kubernetes/kubernetes",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://groups.google.com/g/kubernetes-security-announce/c/vPWYJ_L84m8",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "http://www.openwall.com/lists/oss-security/2023/07/06/2",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "6.5",
+ "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ },
+ {
+ "system": "generic_textual",
+ "value": "MODERATE",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2023-07-03T21:30:57+00:00",
+ "weaknesses": [
+ 20
+ ],
+ "url": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/github_osv_test_5.json"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_expected_6.json b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_6.json
new file mode 100644
index 000000000..a2aa7984c
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_6.json
@@ -0,0 +1,91 @@
+{
+ "aliases": [
+ "GHSA-pffg-92cg-xf5c"
+ ],
+ "summary": "gnark-crypto's exponentiation in the pairing target group GT using GLV can give incorrect results\n### Impact\nWhen the exponent is bigger than `r`, the group order of the pairing target group `GT`, the exponentiation à la GLV (`ExpGLV`) can *sometimes* give incorrect results compared to normal exponentiation (`Exp`). \n\nThe issue impacts all users using `ExpGLV` for exponentiations in `GT`. This does not impact `Exp` and `ExpCyclotomic` which are sound. Also note that GLV methods in G1 and G2 are sound and _not_ impacted.\n\n### Patches\nFix has been implemented in pull request https://github.com/Consensys/gnark-crypto/pull/451 and merged in commit https://github.com/Consensys/gnark-crypto/commit/ec6be1a037f7c496d595c541a8a8d31c47bcfa3d to master branch.\n\nThe fix increased the bounds of the sub-scalars by 1. In fact, since https://github.com/Consensys/gnark-crypto/pull/213, we use a fast scalar decomposition that tradeoffs divisions (needed in the Babai rounding) by right-shifts. We precompute `b=2^m*v/d (m > log2(d))` and then at runtime compute `scalar*b/2^m` (`v` is a lattice vector and `d` the lattice determinant). This increases the bounds on sub-scalars by 1 which we check at runtime before increasing the loop size (we don't target constant-timeness). `m` is chosen to be a machine word twice big than `log2(d)` so that we rarely need to increase the loop size. Hence why the issue happens only *sometimes* if we omit to increase the bounds. This bounds increase was implemented in G1 and G2 but forgot in GT.\n\n### Workarounds\nUpdating to `v0.12.1+`. Alternatively, use `Exp` or `ExpCyclotomic` instead. We are not aware of any users using `ExpGLV` anyway.\n\n### References\n- Fix PR: https://github.com/Consensys/gnark-crypto/pull/451 \n- Fast scalar decomposition PR: https://github.com/Consensys/gnark-crypto/pull/213\n- https://eprint.iacr.org/2015/565 Sec.4.2\n\n### Acknowledgement\nThe vulnerability was reported by [Antonio Sanso](https://github.com/asanso) @ [EF](https://crypto.ethereum.org/).",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "golang",
+ "namespace": "github.com/consensys",
+ "name": "gnark-crypto",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": null,
+ "fixed_version": "0.12.1"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://github.com/Consensys/gnark-crypto/security/advisories/GHSA-pffg-92cg-xf5c",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "LOW",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/Consensys/gnark-crypto/pull/213",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "LOW",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/Consensys/gnark-crypto/pull/451",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "LOW",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/Consensys/gnark-crypto/commit/ec6be1a037f7c496d595c541a8a8d31c47bcfa3d",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "LOW",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://eprint.iacr.org/2015/565",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "LOW",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/Consensys/gnark-crypto",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "LOW",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2023-10-05T20:57:20+00:00",
+ "weaknesses": [],
+ "url": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/github_osv_test_6.json"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_expected_7.json b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_7.json
new file mode 100644
index 000000000..c38362a20
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_expected_7.json
@@ -0,0 +1,150 @@
+{
+ "aliases": [
+ "CVE-2023-36796",
+ "GHSA-h7jm-g87p-5935"
+ ],
+ "summary": "# Microsoft Security Advisory CVE-2023-36796: .NET Remote Code Execution Vulnerability\n\n## Executive summary\n\nMicrosoft is releasing this security advisory to provide information about a vulnerability in .NET 7.0 and .NET 6.0. This advisory also provides guidance on what developers can do to update their applications to remove this vulnerability.\n\nA vulnerability exists in Microsoft.DiaSymReader.Native.amd64.dll when reading a corrupted PDB file which may lead to remote code execution. This issue only affects Windows systems.\n\n**Note:** The vulnerabilities [CVE-2023-36792]( https://www.cve.org/CVERecord?id=CVE-2023-36792), [CVE-2023-36793]( https://www.cve.org/CVERecord?id=CVE-2023-36793), [CVE-2023-36792]( https://www.cve.org/CVERecord?id=CVE-2023-36794), [CVE-2023-36796]( https://www.cve.org/CVERecord?id=CVE-2023-36796) are all resolved by a single patch. Get [affected software](#affected-software) to resolve all of them.\n\n## Discussion\n\nDiscussion for this issue can be found at https://github.com/dotnet/runtime/issues/91948\n\n### Mitigation factors\n\nMicrosoft has not identified any mitigating factors for this vulnerability.\n\n## Affected software\n\n* Any .NET 7.0 application running on .NET 7.0.10 or earlier.\n* Any .NET 6.0 application running on .NET 6.0.21 or earlier.\n\nIf your application uses the following package versions, ensure you update to the latest version of .NET.\n\n### .NET 7\n\nPackage name | Affected version | Patched version\n------------ | ---------------- | -------------------------\n[Microsoft.NETCore.App.Runtime.win-arm64](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-arm64) | >= 7.0.0, <= 7.0.10 | 7.0.11\n[Microsoft.NETCore.App.Runtime.win-x64](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-x64) | >= 7.0.0, <= 7.0.10 | 7.0.11\n[Microsoft.NETCore.App.Runtime.win-x86](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-x86) | >= 7.0.0, <= 7.0.10 | 7.0.11\n\n### .NET 6\n\nPackage name | Affected version | Patched version\n------------ | ---------------- | -------------------------\n[Microsoft.NETCore.App.Runtime.win-arm64](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-arm64) | >= 6.0.0, <= 6.0.21 | 6.0.22\n[Microsoft.NETCore.App.Runtime.win-x64](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-x64) | >= 6.0.0, <= 6.0.21 | 6.0.22\n[Microsoft.NETCore.App.Runtime.win-x86](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-x86) | >= 6.0.0, <= 6.0.21 | 6.0.22\n\n\n## Advisory FAQ\n\n### How do I know if I am affected?\n\nIf you have a runtime or SDK with a version listed, or an affected package listed in [affected software](#affected-software), you're exposed to the vulnerability.\n\n### How do I fix the issue?\n\n* To fix the issue please install the latest version of .NET 6.0 or .NET 7.0. If you have installed one or more .NET SDKs through Visual Studio, Visual Studio will prompt you to update Visual Studio, which will also update your .NET SDKs.\n* If you are using one of the affected packages, please update to the patched version listed above.\n* If you have .NET 6.0 or greater installed, you can list the versions you have installed by running the `dotnet --info` command. You will see output like the following;\n\n```\n.NET Core SDK (reflecting any global.json):\n\n Version: 6.0.300\n Commit: 8473146e7d\n\nRuntime Environment:\n\n OS Name: Windows\n OS Version: 10.0.18363\n OS Platform: Windows\n RID: win10-x64\n Base Path: C:\\Program Files\\dotnet\\sdk\\6.0.300\\\n\nHost (useful for support):\n\n Version: 6.0.5\n Commit: 8473146e7d\n\n.NET Core SDKs installed:\n\n 6.0.300 [C:\\Program Files\\dotnet\\sdk]\n\n.NET Core runtimes installed:\n\n Microsoft.AspNetCore.App 6.0.5 [C:\\Program Files\\dotnet\\shared\\Microsoft.AspNetCore.App]\n Microsoft.NETCore.App 6.0.5 [C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App]\n Microsoft.WindowsDesktop.App 6.0.5 [C:\\Program Files\\dotnet\\shared\\Microsoft.WindowsDesktop.App]\n\nTo install additional .NET Core runtimes or SDKs:\n https://aka.ms/dotnet-download\n```\n\n* If you're using .NET 7.0, you should download and install Runtime 7.0.11 or SDK 7.0.111 (for Visual Studio 2022 v17.4) from https://dotnet.microsoft.com/download/dotnet-core/7.0.\n* If you're using .NET 6.0, you should download and install Runtime 6.0.22 or SDK 6.0.317 (for Visual Studio 2022 v17.2) from https://dotnet.microsoft.com/download/dotnet-core/6.0.\n\n.NET 6.0 and and .NET 7.0 updates are also available from Microsoft Update. To access this either type \"Check for updates\" in your Windows search, or open Settings, choose Update & Security and then click Check for Updates.\n\nOnce you have installed the updated runtime or SDK, restart your apps for the update to take effect.\n\nAdditionally, if you've deployed [self-contained applications](https://docs.microsoft.com/dotnet/core/deploying/#self-contained-deployments-scd) targeting any of the impacted versions, these applications are also vulnerable and must be recompiled and redeployed.\n\n## Other Information\n\n### Reporting Security Issues\n\nIf you have found a potential security issue in .NET 6.0 or .NET 7.0, please email details to secure@microsoft.com. Reports may qualify for the Microsoft .NET Core & .NET 5 Bounty. Details of the Microsoft .NET Bounty Program including terms and conditions are at .\n\n### Support\n\nYou can ask questions about this issue on GitHub in the .NET GitHub organization. The main repos are located at https://github.com/dotnet/runtime and https://github.com/dotnet/aspnet/. The Announcements repo (https://github.com/dotnet/Announcements) will contain this bulletin as an issue and will include a link to a discussion issue. You can ask questions in the linked discussion issue.\n\n### Disclaimer\n\nThe information provided in this advisory is provided \"as is\" without warranty of any kind. Microsoft disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. In no event shall Microsoft Corporation or its suppliers be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages, even if Microsoft Corporation or its suppliers have been advised of the possibility of such damages. Some states do not allow the exclusion or limitation of liability for consequential or incidental damages so the foregoing limitation may not apply.\n\n### External Links\n\n[CVE-2023-36796]( https://www.cve.org/CVERecord?id=CVE-2023-36796)\n\n### Revisions\n\nV1.0 (September 12, 2023): Advisory published.\n\n_Version 1.0_\n\n_Last Updated 2023-09-12_",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "nuget",
+ "namespace": "",
+ "name": "Microsoft.NETCore.App.Runtime.win-arm64",
+ "version": "",
+ "qualifiers": "",
+ "subpath": ""
+ },
+ "affected_version_range": null,
+ "fixed_version": "7.0.11"
+ },
+ {
+ "package": {
+ "type": "nuget",
+ "namespace": "",
+ "name": "Microsoft.NETCore.App.Runtime.win-arm64",
+ "version": "",
+ "qualifiers": "",
+ "subpath": ""
+ },
+ "affected_version_range": null,
+ "fixed_version": "6.0.22"
+ },
+ {
+ "package": {
+ "type": "nuget",
+ "namespace": "",
+ "name": "Microsoft.NETCore.App.Runtime.win-x64",
+ "version": "",
+ "qualifiers": "",
+ "subpath": ""
+ },
+ "affected_version_range": null,
+ "fixed_version": "7.0.11"
+ },
+ {
+ "package": {
+ "type": "nuget",
+ "namespace": "",
+ "name": "Microsoft.NETCore.App.Runtime.win-x64",
+ "version": "",
+ "qualifiers": "",
+ "subpath": ""
+ },
+ "affected_version_range": null,
+ "fixed_version": "6.0.22"
+ },
+ {
+ "package": {
+ "type": "nuget",
+ "namespace": "",
+ "name": "Microsoft.NETCore.App.Runtime.win-x86",
+ "version": "",
+ "qualifiers": "",
+ "subpath": ""
+ },
+ "affected_version_range": null,
+ "fixed_version": "6.0.22"
+ },
+ {
+ "package": {
+ "type": "nuget",
+ "namespace": "",
+ "name": "Microsoft.NETCore.App.Runtime.win-x86",
+ "version": "",
+ "qualifiers": "",
+ "subpath": ""
+ },
+ "affected_version_range": null,
+ "fixed_version": "7.0.11"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://github.com/dotnet/runtime/security/advisories/GHSA-h7jm-g87p-5935",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.8",
+ "scoring_elements": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-36796",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.8",
+ "scoring_elements": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/dotnet/runtime",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.8",
+ "scoring_elements": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2023-36796",
+ "severities": [
+ {
+ "system": "cvssv3.1",
+ "value": "7.8",
+ "scoring_elements": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"
+ },
+ {
+ "system": "generic_textual",
+ "value": "HIGH",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2023-09-12T20:05:18+00:00",
+ "weaknesses": [],
+ "url": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/github_osv_test_7.json"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_test_1.json b/vulnerabilities/tests/test_data/github_osv/github_osv_test_1.json
new file mode 100644
index 000000000..02583ee61
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_test_1.json
@@ -0,0 +1,71 @@
+{
+ "schema_version": "1.3.0",
+ "id": "GHSA-3fx5-fwvr-xrjg",
+ "modified": "2021-09-22T20:19:52Z",
+ "published": "2017-10-24T18:33:36Z",
+ "aliases": [
+ "CVE-2015-8315"
+ ],
+ "summary": "Regular Expression Denial of Service in ms",
+ "details": "Versions of `ms` prior to 0.7.1 are affected by a regular expression denial of service vulnerability when extremely long version strings are parsed.\n\n## Proof of Concept\n```javascript\nvar ms = require('ms');\nvar genstr = function (len, chr) {\n var result = \"\";\n for (i=0; i<=len; i++) {\n result = result + chr;\n }\n\n return result;\n}\n\nms(genstr(process.argv[2], \"5\") + \" minutea\");\n\n```\n\n### Results\nShowing increase in execution time based on the input string.\n```\n$ time node ms.js 10000\n\nreal\t0m0.758s\nuser\t0m0.724s\nsys\t0m0.031s\n\n$ time node ms.js 20000\n\nreal\t0m2.580s\nuser\t0m2.494s\nsys\t0m0.047s\n\n$ time node ms.js 30000\n\nreal\t0m5.747s\nuser\t0m5.483s\nsys\t0m0.080s\n\n$ time node ms.js 80000\n\nreal\t0m41.022s\nuser\t0m38.894s\nsys\t0m0.529s\n```\n",
+ "severity": [
+ {
+ "type": "CVSS_V3",
+ "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ }
+ ],
+ "affected": [
+ {
+ "package": {
+ "ecosystem": "npm",
+ "name": "ms"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "0.7.1"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "references": [
+ {
+ "type": "ADVISORY",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2015-8315"
+ },
+ {
+ "type": "PACKAGE",
+ "url": "https://github.com/unshiftio/millisecond/"
+ },
+ {
+ "type": "WEB",
+ "url": "https://support.f5.com/csp/article/K46337613?utm_source=f5support&utm_medium=RSS"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.npmjs.com/advisories/46"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.openwall.com/lists/oss-security/2016/04/20/11"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.securityfocus.com/bid/96389"
+ }
+ ],
+ "database_specific": {
+ "cwe_ids": [
+ "CWE-400"
+ ],
+ "severity": "HIGH",
+ "github_reviewed": true
+ }
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_test_2.json b/vulnerabilities/tests/test_data/github_osv/github_osv_test_2.json
new file mode 100644
index 000000000..fef8553f2
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_test_2.json
@@ -0,0 +1,63 @@
+{
+ "schema_version": "1.3.0",
+ "id": "GHSA-3qr6-qrqm-8v86",
+ "modified": "2022-03-30T20:02:35Z",
+ "published": "2022-03-23T00:00:23Z",
+ "aliases": [
+ "CVE-2022-1036"
+ ],
+ "summary": "Integer Overflow or Wraparound in Microweber",
+ "details": "In Microweber prior to 1.2.12, a user can create an account with a password thousands of characters in length, leading to memory corruption/integer overflow. Version 1.2.2 sets maximum password length at 500 characters.",
+ "severity": [
+ {
+ "type": "CVSS_V3",
+ "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
+ }
+ ],
+ "affected": [
+ {
+ "package": {
+ "ecosystem": "Packagist",
+ "name": "microweber/microweber"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "1.2.12"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "references": [
+ {
+ "type": "ADVISORY",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-1036"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/microweber/microweber/commit/82be4f0b4729be870ccefdae99a04833f134aa6a"
+ },
+ {
+ "type": "PACKAGE",
+ "url": "https://github.com/microweber/microweber"
+ },
+ {
+ "type": "WEB",
+ "url": "https://huntr.dev/bounties/db615581-d5a9-4ca5-a3e9-7a39eceaa424"
+ }
+ ],
+ "database_specific": {
+ "cwe_ids": [
+ "CWE-190"
+ ],
+ "severity": "HIGH",
+ "github_reviewed": true
+ }
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_test_3.json b/vulnerabilities/tests/test_data/github_osv/github_osv_test_3.json
new file mode 100644
index 000000000..f8a3f0f44
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_test_3.json
@@ -0,0 +1,136 @@
+{
+ "schema_version": "1.3.0",
+ "id": "GHSA-29qj-rvv6-qrmv",
+ "modified": "2021-06-01T20:09:20Z",
+ "published": "2021-06-15T16:05:22Z",
+ "aliases": [
+ "CVE-2020-10688"
+ ],
+ "summary": "Cross-site scripting in RESTEasy",
+ "details": "A cross-site scripting (XSS) flaw was found in RESTEasy in versions before 3.11.1.Final and before 4.5.3.Final, where it did not properly handle URL encoding when the RESTEASY003870 exception occurs. An attacker could use this flaw to launch a reflected XSS attack.",
+ "severity": [
+ {
+ "type": "CVSS_V3",
+ "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N"
+ }
+ ],
+ "affected": [
+ {
+ "package": {
+ "ecosystem": "Maven",
+ "name": "org.jboss.resteasy:resteasy-bom"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "3.11.1.Final"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 3.11.0.Final"
+ }
+ },
+ {
+ "package": {
+ "ecosystem": "Maven",
+ "name": "org.jboss.resteasy:resteasy-bom"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "4.0.0"
+ },
+ {
+ "fixed": "4.5.3.Final"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 4.5.2.Final"
+ }
+ },
+ {
+ "package": {
+ "ecosystem": "Maven",
+ "name": "org.jboss.resteasy:resteasy-core"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "3.11.1.Final"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 3.11.0.Final"
+ }
+ },
+ {
+ "package": {
+ "ecosystem": "Maven",
+ "name": "org.jboss.resteasy:resteasy-core"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "4.0.0"
+ },
+ {
+ "fixed": "4.5.3.Final"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 4.5.2.Final"
+ }
+ }
+ ],
+ "references": [
+ {
+ "type": "ADVISORY",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-10688"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/quarkusio/quarkus/issues/7248"
+ },
+ {
+ "type": "WEB",
+ "url": "https://bugzilla.redhat.com/show_bug.cgi?id=1814974"
+ },
+ {
+ "type": "WEB",
+ "url": "https://issues.redhat.com/browse/RESTEASY-2519"
+ },
+ {
+ "type": "WEB",
+ "url": "https://security.netapp.com/advisory/ntap-20210706-0008/"
+ }
+ ],
+ "database_specific": {
+ "cwe_ids": [
+ "CWE-79"
+ ],
+ "severity": "MODERATE",
+ "github_reviewed": true
+ }
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_test_4.json b/vulnerabilities/tests/test_data/github_osv/github_osv_test_4.json
new file mode 100644
index 000000000..9ce660a2b
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_test_4.json
@@ -0,0 +1,119 @@
+{
+ "schema_version": "1.3.0",
+ "id": "GHSA-24fg-p96v-hxh8",
+ "modified": "2020-06-16T20:51:22Z",
+ "published": "2017-10-24T18:33:38Z",
+ "aliases": [
+ "CVE-2011-0447"
+ ],
+ "summary": "Moderate severity vulnerability that affects rails",
+ "details": "Ruby on Rails 2.1.x, 2.2.x, and 2.3.x before 2.3.11, and 3.x before 3.0.4, does not properly validate HTTP requests that contain an X-Requested-With header, which makes it easier for remote attackers to conduct cross-site request forgery (CSRF) attacks via forged (1) AJAX or (2) API requests that leverage \"combinations of browser plugins and HTTP redirects,\" a related issue to CVE-2011-0696.",
+ "severity": [
+
+ ],
+ "affected": [
+ {
+ "package": {
+ "ecosystem": "RubyGems",
+ "name": "rails"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "2.1.0"
+ },
+ {
+ "fixed": "2.3.11"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "package": {
+ "ecosystem": "RubyGems",
+ "name": "rails"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "3.0.0"
+ },
+ {
+ "fixed": "3.0.4"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "references": [
+ {
+ "type": "ADVISORY",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2011-0447"
+ },
+ {
+ "type": "ADVISORY",
+ "url": "https://github.com/advisories/GHSA-24fg-p96v-hxh8"
+ },
+ {
+ "type": "WEB",
+ "url": "http://groups.google.com/group/rubyonrails-security/msg/c22ea1668c0d181c?dmode=source&output=gplain"
+ },
+ {
+ "type": "WEB",
+ "url": "http://lists.fedoraproject.org/pipermail/package-announce/2011-April/057650.html"
+ },
+ {
+ "type": "WEB",
+ "url": "http://lists.fedoraproject.org/pipermail/package-announce/2011-March/055074.html"
+ },
+ {
+ "type": "WEB",
+ "url": "http://lists.fedoraproject.org/pipermail/package-announce/2011-March/055088.html"
+ },
+ {
+ "type": "WEB",
+ "url": "http://secunia.com/advisories/43274"
+ },
+ {
+ "type": "WEB",
+ "url": "http://secunia.com/advisories/43666"
+ },
+ {
+ "type": "WEB",
+ "url": "http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.debian.org/security/2011/dsa-2247"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.securityfocus.com/bid/46291"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.securitytracker.com/id?1025060"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.vupen.com/english/advisories/2011/0587"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.vupen.com/english/advisories/2011/0877"
+ }
+ ],
+ "database_specific": {
+ "cwe_ids": [
+ "CWE-352"
+ ],
+ "severity": "MODERATE",
+ "github_reviewed": true
+ }
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_test_5.json b/vulnerabilities/tests/test_data/github_osv/github_osv_test_5.json
new file mode 100644
index 000000000..f4e715047
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_test_5.json
@@ -0,0 +1,146 @@
+{
+ "schema_version": "1.4.0",
+ "id": "GHSA-qc2g-gmh6-95p4",
+ "modified": "2023-07-05T22:46:57Z",
+ "published": "2023-07-03T21:30:57Z",
+ "aliases": [
+ "CVE-2023-2727"
+ ],
+ "summary": "kube-apiserver vulnerable to policy bypass",
+ "details": "Users may be able to launch containers using images that are restricted by ImagePolicyWebhook when using ephemeral containers. Kubernetes clusters are only affected if the ImagePolicyWebhook admission plugin is used together with ephemeral containers.\n\n",
+ "severity": [
+ {
+ "type": "CVSS_V3",
+ "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N"
+ }
+ ],
+ "affected": [
+ {
+ "package": {
+ "ecosystem": "Go",
+ "name": "k8s.io/kubernetes"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "1.27.0"
+ },
+ {
+ "fixed": "1.27.3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "package": {
+ "ecosystem": "Go",
+ "name": "k8s.io/kubernetes"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "1.26.0"
+ },
+ {
+ "fixed": "1.26.6"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "package": {
+ "ecosystem": "Go",
+ "name": "k8s.io/kubernetes"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "1.25.0"
+ },
+ {
+ "fixed": "1.25.11"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "package": {
+ "ecosystem": "Go",
+ "name": "k8s.io/kubernetes"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "1.24.15"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "references": [
+ {
+ "type": "ADVISORY",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-2727"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/kubernetes/kubernetes/issues/118640"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118356"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118471"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118473"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118474"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/kubernetes/kubernetes/pull/118512"
+ },
+ {
+ "type": "PACKAGE",
+ "url": "https://github.com/kubernetes/kubernetes"
+ },
+ {
+ "type": "WEB",
+ "url": "https://groups.google.com/g/kubernetes-security-announce/c/vPWYJ_L84m8"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.openwall.com/lists/oss-security/2023/07/06/2"
+ }
+ ],
+ "database_specific": {
+ "cwe_ids": [
+ "CWE-20"
+ ],
+ "severity": "MODERATE",
+ "github_reviewed": true,
+ "github_reviewed_at": "2023-07-05T22:46:57Z",
+ "nvd_published_at": "2023-07-03T21:15:09Z"
+ }
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_test_6.json b/vulnerabilities/tests/test_data/github_osv/github_osv_test_6.json
new file mode 100644
index 000000000..f9e97c05f
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_test_6.json
@@ -0,0 +1,73 @@
+{
+ "schema_version": "1.4.0",
+ "id": "GHSA-pffg-92cg-xf5c",
+ "modified": "2023-11-08T18:36:33Z",
+ "published": "2023-10-05T20:57:20Z",
+ "aliases": [
+
+ ],
+ "summary": "gnark-crypto's exponentiation in the pairing target group GT using GLV can give incorrect results",
+ "details": "### Impact\nWhen the exponent is bigger than `r`, the group order of the pairing target group `GT`, the exponentiation à la GLV (`ExpGLV`) can *sometimes* give incorrect results compared to normal exponentiation (`Exp`). \n\nThe issue impacts all users using `ExpGLV` for exponentiations in `GT`. This does not impact `Exp` and `ExpCyclotomic` which are sound. Also note that GLV methods in G1 and G2 are sound and _not_ impacted.\n\n### Patches\nFix has been implemented in pull request https://github.com/Consensys/gnark-crypto/pull/451 and merged in commit https://github.com/Consensys/gnark-crypto/commit/ec6be1a037f7c496d595c541a8a8d31c47bcfa3d to master branch.\n\nThe fix increased the bounds of the sub-scalars by 1. In fact, since https://github.com/Consensys/gnark-crypto/pull/213, we use a fast scalar decomposition that tradeoffs divisions (needed in the Babai rounding) by right-shifts. We precompute `b=2^m*v/d (m > log2(d))` and then at runtime compute `scalar*b/2^m` (`v` is a lattice vector and `d` the lattice determinant). This increases the bounds on sub-scalars by 1 which we check at runtime before increasing the loop size (we don't target constant-timeness). `m` is chosen to be a machine word twice big than `log2(d)` so that we rarely need to increase the loop size. Hence why the issue happens only *sometimes* if we omit to increase the bounds. This bounds increase was implemented in G1 and G2 but forgot in GT.\n\n### Workarounds\nUpdating to `v0.12.1+`. Alternatively, use `Exp` or `ExpCyclotomic` instead. We are not aware of any users using `ExpGLV` anyway.\n\n### References\n- Fix PR: https://github.com/Consensys/gnark-crypto/pull/451 \n- Fast scalar decomposition PR: https://github.com/Consensys/gnark-crypto/pull/213\n- https://eprint.iacr.org/2015/565 Sec.4.2\n\n### Acknowledgement\nThe vulnerability was reported by [Antonio Sanso](https://github.com/asanso) @ [EF](https://crypto.ethereum.org/).\n",
+ "severity": [
+
+ ],
+ "affected": [
+ {
+ "package": {
+ "ecosystem": "Go",
+ "name": "github.com/consensys/gnark-crypto"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "0.12.1"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 0.12.0"
+ }
+ }
+ ],
+ "references": [
+ {
+ "type": "WEB",
+ "url": "https://github.com/Consensys/gnark-crypto/security/advisories/GHSA-pffg-92cg-xf5c"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/Consensys/gnark-crypto/pull/213"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/Consensys/gnark-crypto/pull/451"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/Consensys/gnark-crypto/commit/ec6be1a037f7c496d595c541a8a8d31c47bcfa3d"
+ },
+ {
+ "type": "WEB",
+ "url": "https://eprint.iacr.org/2015/565"
+ },
+ {
+ "type": "PACKAGE",
+ "url": "https://github.com/Consensys/gnark-crypto"
+ }
+ ],
+ "database_specific": {
+ "cwe_ids": [
+
+ ],
+ "severity": "LOW",
+ "github_reviewed": true,
+ "github_reviewed_at": "2023-10-05T20:57:20Z",
+ "nvd_published_at": null
+ }
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/github_osv/github_osv_test_7.json b/vulnerabilities/tests/test_data/github_osv/github_osv_test_7.json
new file mode 100644
index 000000000..b7bac4bf0
--- /dev/null
+++ b/vulnerabilities/tests/test_data/github_osv/github_osv_test_7.json
@@ -0,0 +1,178 @@
+{
+ "schema_version": "1.4.0",
+ "id": "GHSA-h7jm-g87p-5935",
+ "modified": "2023-09-12T20:05:18Z",
+ "published": "2023-09-12T20:05:18Z",
+ "aliases": [
+ "CVE-2023-36796"
+ ],
+ "summary": "Microsoft Security Advisory CVE-2023-36796: .NET Remote Code Execution Vulnerability",
+ "details": "# Microsoft Security Advisory CVE-2023-36796: .NET Remote Code Execution Vulnerability\n\n## Executive summary\n\nMicrosoft is releasing this security advisory to provide information about a vulnerability in .NET 7.0 and .NET 6.0. This advisory also provides guidance on what developers can do to update their applications to remove this vulnerability.\n\nA vulnerability exists in Microsoft.DiaSymReader.Native.amd64.dll when reading a corrupted PDB file which may lead to remote code execution. This issue only affects Windows systems.\n\n**Note:** The vulnerabilities [CVE-2023-36792]( https://www.cve.org/CVERecord?id=CVE-2023-36792), [CVE-2023-36793]( https://www.cve.org/CVERecord?id=CVE-2023-36793), [CVE-2023-36792]( https://www.cve.org/CVERecord?id=CVE-2023-36794), [CVE-2023-36796]( https://www.cve.org/CVERecord?id=CVE-2023-36796) are all resolved by a single patch. Get [affected software](#affected-software) to resolve all of them.\n\n## Discussion\n\nDiscussion for this issue can be found at https://github.com/dotnet/runtime/issues/91948\n\n### Mitigation factors\n\nMicrosoft has not identified any mitigating factors for this vulnerability.\n\n## Affected software\n\n* Any .NET 7.0 application running on .NET 7.0.10 or earlier.\n* Any .NET 6.0 application running on .NET 6.0.21 or earlier.\n\nIf your application uses the following package versions, ensure you update to the latest version of .NET.\n\n### .NET 7\n\nPackage name | Affected version | Patched version\n------------ | ---------------- | -------------------------\n[Microsoft.NETCore.App.Runtime.win-arm64](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-arm64) | >= 7.0.0, <= 7.0.10 | 7.0.11\n[Microsoft.NETCore.App.Runtime.win-x64](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-x64) | >= 7.0.0, <= 7.0.10 | 7.0.11\n[Microsoft.NETCore.App.Runtime.win-x86](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-x86) | >= 7.0.0, <= 7.0.10 | 7.0.11\n\n### .NET 6\n\nPackage name | Affected version | Patched version\n------------ | ---------------- | -------------------------\n[Microsoft.NETCore.App.Runtime.win-arm64](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-arm64) | >= 6.0.0, <= 6.0.21 | 6.0.22\n[Microsoft.NETCore.App.Runtime.win-x64](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-x64) | >= 6.0.0, <= 6.0.21 | 6.0.22\n[Microsoft.NETCore.App.Runtime.win-x86](https://www.nuget.org/packages/Microsoft.NETCore.App.Runtime.win-x86) | >= 6.0.0, <= 6.0.21 | 6.0.22\n\n\n## Advisory FAQ\n\n### How do I know if I am affected?\n\nIf you have a runtime or SDK with a version listed, or an affected package listed in [affected software](#affected-software), you're exposed to the vulnerability.\n\n### How do I fix the issue?\n\n* To fix the issue please install the latest version of .NET 6.0 or .NET 7.0. If you have installed one or more .NET SDKs through Visual Studio, Visual Studio will prompt you to update Visual Studio, which will also update your .NET SDKs.\n* If you are using one of the affected packages, please update to the patched version listed above.\n* If you have .NET 6.0 or greater installed, you can list the versions you have installed by running the `dotnet --info` command. You will see output like the following;\n\n```\n.NET Core SDK (reflecting any global.json):\n\n Version: 6.0.300\n Commit: 8473146e7d\n\nRuntime Environment:\n\n OS Name: Windows\n OS Version: 10.0.18363\n OS Platform: Windows\n RID: win10-x64\n Base Path: C:\\Program Files\\dotnet\\sdk\\6.0.300\\\n\nHost (useful for support):\n\n Version: 6.0.5\n Commit: 8473146e7d\n\n.NET Core SDKs installed:\n\n 6.0.300 [C:\\Program Files\\dotnet\\sdk]\n\n.NET Core runtimes installed:\n\n Microsoft.AspNetCore.App 6.0.5 [C:\\Program Files\\dotnet\\shared\\Microsoft.AspNetCore.App]\n Microsoft.NETCore.App 6.0.5 [C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App]\n Microsoft.WindowsDesktop.App 6.0.5 [C:\\Program Files\\dotnet\\shared\\Microsoft.WindowsDesktop.App]\n\nTo install additional .NET Core runtimes or SDKs:\n https://aka.ms/dotnet-download\n```\n\n* If you're using .NET 7.0, you should download and install Runtime 7.0.11 or SDK 7.0.111 (for Visual Studio 2022 v17.4) from https://dotnet.microsoft.com/download/dotnet-core/7.0.\n* If you're using .NET 6.0, you should download and install Runtime 6.0.22 or SDK 6.0.317 (for Visual Studio 2022 v17.2) from https://dotnet.microsoft.com/download/dotnet-core/6.0.\n\n.NET 6.0 and and .NET 7.0 updates are also available from Microsoft Update. To access this either type \"Check for updates\" in your Windows search, or open Settings, choose Update & Security and then click Check for Updates.\n\nOnce you have installed the updated runtime or SDK, restart your apps for the update to take effect.\n\nAdditionally, if you've deployed [self-contained applications](https://docs.microsoft.com/dotnet/core/deploying/#self-contained-deployments-scd) targeting any of the impacted versions, these applications are also vulnerable and must be recompiled and redeployed.\n\n## Other Information\n\n### Reporting Security Issues\n\nIf you have found a potential security issue in .NET 6.0 or .NET 7.0, please email details to secure@microsoft.com. Reports may qualify for the Microsoft .NET Core & .NET 5 Bounty. Details of the Microsoft .NET Bounty Program including terms and conditions are at .\n\n### Support\n\nYou can ask questions about this issue on GitHub in the .NET GitHub organization. The main repos are located at https://github.com/dotnet/runtime and https://github.com/dotnet/aspnet/. The Announcements repo (https://github.com/dotnet/Announcements) will contain this bulletin as an issue and will include a link to a discussion issue. You can ask questions in the linked discussion issue.\n\n### Disclaimer\n\nThe information provided in this advisory is provided \"as is\" without warranty of any kind. Microsoft disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. In no event shall Microsoft Corporation or its suppliers be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages, even if Microsoft Corporation or its suppliers have been advised of the possibility of such damages. Some states do not allow the exclusion or limitation of liability for consequential or incidental damages so the foregoing limitation may not apply.\n\n### External Links\n\n[CVE-2023-36796]( https://www.cve.org/CVERecord?id=CVE-2023-36796)\n\n### Revisions\n\nV1.0 (September 12, 2023): Advisory published.\n\n_Version 1.0_\n\n_Last Updated 2023-09-12_",
+ "severity": [
+ {
+ "type": "CVSS_V3",
+ "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"
+ }
+ ],
+ "affected": [
+ {
+ "package": {
+ "ecosystem": "NuGet",
+ "name": "Microsoft.NETCore.App.Runtime.win-arm64"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "7.0.0"
+ },
+ {
+ "fixed": "7.0.11"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 7.0.10"
+ }
+ },
+ {
+ "package": {
+ "ecosystem": "NuGet",
+ "name": "Microsoft.NETCore.App.Runtime.win-arm64"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "6.0.0"
+ },
+ {
+ "fixed": "6.0.22"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 6.0.21"
+ }
+ },
+ {
+ "package": {
+ "ecosystem": "NuGet",
+ "name": "Microsoft.NETCore.App.Runtime.win-x64"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "7.0.0"
+ },
+ {
+ "fixed": "7.0.11"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 7.0.10"
+ }
+ },
+ {
+ "package": {
+ "ecosystem": "NuGet",
+ "name": "Microsoft.NETCore.App.Runtime.win-x64"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "6.0.0"
+ },
+ {
+ "fixed": "6.0.22"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 6.0.21"
+ }
+ },
+ {
+ "package": {
+ "ecosystem": "NuGet",
+ "name": "Microsoft.NETCore.App.Runtime.win-x86"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "6.0.0"
+ },
+ {
+ "fixed": "6.0.22"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 6.0.21"
+ }
+ },
+ {
+ "package": {
+ "ecosystem": "NuGet",
+ "name": "Microsoft.NETCore.App.Runtime.win-x86"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "7.0.0"
+ },
+ {
+ "fixed": "7.0.11"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "last_known_affected_version_range": "<= 7.0.10"
+ }
+ }
+ ],
+ "references": [
+ {
+ "type": "WEB",
+ "url": "https://github.com/dotnet/runtime/security/advisories/GHSA-h7jm-g87p-5935"
+ },
+ {
+ "type": "ADVISORY",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-36796"
+ },
+ {
+ "type": "PACKAGE",
+ "url": "https://github.com/dotnet/runtime"
+ },
+ {
+ "type": "WEB",
+ "url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2023-36796"
+ }
+ ],
+ "database_specific": {
+ "cwe_ids": [
+
+ ],
+ "severity": "HIGH",
+ "github_reviewed": true,
+ "github_reviewed_at": "2023-09-12T20:05:18Z",
+ "nvd_published_at": "2023-09-12T17:15:15Z"
+ }
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/pypa/pypa-expected.json b/vulnerabilities/tests/test_data/pypa/pypa-expected.json
index bf49770a5..1a907bd05 100644
--- a/vulnerabilities/tests/test_data/pypa/pypa-expected.json
+++ b/vulnerabilities/tests/test_data/pypa/pypa-expected.json
@@ -67,5 +67,5 @@
],
"date_published": "2022-01-05T00:15:00+00:00",
"weaknesses": [],
- "url": "https://github.com/pypa/advisory-database"
+ "url": "https://github.com/pypa/advisory-database/blob/main/vulns/pypa-expected.json"
}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/ruby/CVE-2007-5770-expected.json b/vulnerabilities/tests/test_data/ruby/CVE-2007-5770-expected.json
new file mode 100644
index 000000000..aa3b4088c
--- /dev/null
+++ b/vulnerabilities/tests/test_data/ruby/CVE-2007-5770-expected.json
@@ -0,0 +1,42 @@
+{
+ "aliases": [
+ "CVE-2007-5770"
+ ],
+ "summary": "Ruby Net::HTTPS library does not validate server certificate CN\nThe (1) Net::ftptls, (2) Net::telnets, (3) Net::imap, (4) Net::pop, and (5)\nNet::smtp libraries in Ruby 1.8.5 and 1.8.6 do not verify that the\ncommonName (CN) field in a server certificate matches the domain name in a\nrequest sent over SSL, which makes it easier for remote attackers to\nintercept SSL transmissions via a man-in-the-middle attack or spoofed web\nsite, different components than CVE-2007-5162.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "ruby",
+ "namespace": null,
+ "name": "ruby",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:gem/<1.8.6.230|>=1.8.7",
+ "fixed_version": null
+ },
+ {
+ "package": {
+ "type": "ruby",
+ "namespace": null,
+ "name": "ruby",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:gem/<1.8.7",
+ "fixed_version": null
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "http://www.cvedetails.com/cve/CVE-2007-5770/",
+ "severities": []
+ }
+ ],
+ "date_published": "2007-10-08T00:00:00+00:00",
+ "weaknesses": [],
+ "url": "https://github.com/rubysec/ruby-advisory-db"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/ruby/CVE-2007-5770.yml b/vulnerabilities/tests/test_data/ruby/CVE-2007-5770.yml
new file mode 100644
index 000000000..fcb1c372b
--- /dev/null
+++ b/vulnerabilities/tests/test_data/ruby/CVE-2007-5770.yml
@@ -0,0 +1,17 @@
+---
+engine: ruby
+cve: 2007-5770
+url: http://www.cvedetails.com/cve/CVE-2007-5770/
+title: Ruby Net::HTTPS library does not validate server certificate CN
+date: 2007-10-08
+description: |
+ The (1) Net::ftptls, (2) Net::telnets, (3) Net::imap, (4) Net::pop, and (5)
+ Net::smtp libraries in Ruby 1.8.5 and 1.8.6 do not verify that the
+ commonName (CN) field in a server certificate matches the domain name in a
+ request sent over SSL, which makes it easier for remote attackers to
+ intercept SSL transmissions via a man-in-the-middle attack or spoofed web
+ site, different components than CVE-2007-5162.
+cvss_v2: 4.3
+patched_versions:
+- ~> 1.8.6.230
+- '>= 1.8.7'
diff --git a/vulnerabilities/tests/test_data/ruby/CVE-2010-1330-expected.json b/vulnerabilities/tests/test_data/ruby/CVE-2010-1330-expected.json
new file mode 100644
index 000000000..bd09931cc
--- /dev/null
+++ b/vulnerabilities/tests/test_data/ruby/CVE-2010-1330-expected.json
@@ -0,0 +1,31 @@
+{
+ "aliases": [
+ "CVE-2010-1330",
+ "OSV-77297"
+ ],
+ "summary": "CVE-2010-1330 jruby: XSS in the regular expression engine when processing invalid UTF-8 byte sequences\nThe regular expression engine in JRuby before 1.4.1, when $KCODE is set to 'u', does not properly handle characters immediately after a UTF-8 character, which allows remote attackers to conduct cross-site scripting (XSS) attacks via a crafted string.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "ruby",
+ "namespace": null,
+ "name": "jruby",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:gem/<1.4.1",
+ "fixed_version": null
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "http://jruby.org/2010/04/26/jruby-1-4-1-xss-vulnerability",
+ "severities": []
+ }
+ ],
+ "date_published": "2010-04-26T00:00:00+00:00",
+ "weaknesses": [],
+ "url": "https://github.com/rubysec/ruby-advisory-db"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/ruby/CVE-2010-1330.yml b/vulnerabilities/tests/test_data/ruby/CVE-2010-1330.yml
new file mode 100644
index 000000000..78e0dfdd9
--- /dev/null
+++ b/vulnerabilities/tests/test_data/ruby/CVE-2010-1330.yml
@@ -0,0 +1,15 @@
+---
+engine: jruby
+cve: 2010-1330
+osvdb: 77297
+url: http://jruby.org/2010/04/26/jruby-1-4-1-xss-vulnerability
+title: 'CVE-2010-1330 jruby: XSS in the regular expression engine when processing
+ invalid UTF-8 byte sequences'
+date: 2010-04-26
+description: The regular expression engine in JRuby before 1.4.1, when $KCODE is set
+ to 'u', does not properly handle characters immediately after a UTF-8 character,
+ which allows remote attackers to conduct cross-site scripting (XSS) attacks via
+ a crafted string.
+cvss_v2: 4.3
+patched_versions:
+- '>= 1.4.1'
diff --git a/vulnerabilities/tests/test_data/ruby/CVE-2018-11627-expected.json b/vulnerabilities/tests/test_data/ruby/CVE-2018-11627-expected.json
new file mode 100644
index 000000000..3cc824fa4
--- /dev/null
+++ b/vulnerabilities/tests/test_data/ruby/CVE-2018-11627-expected.json
@@ -0,0 +1,36 @@
+{
+ "aliases": [
+ "CVE-2018-11627"
+ ],
+ "summary": "Sinatra before 2.0.2 has XSS via the 400 Bad Request page that occurs upon a params parser exception.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:gem/<2.0.2",
+ "fixed_version": null
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/issues/1428",
+ "severities": [
+ {
+ "system": "cvssv3",
+ "value": "6.1",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2018-05-31T00:00:00+00:00",
+ "weaknesses": [],
+ "url": "https://github.com/rubysec/ruby-advisory-db"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/ruby/sinatra/CVE-2018-11627.yml b/vulnerabilities/tests/test_data/ruby/CVE-2018-11627.yml
similarity index 100%
rename from vulnerabilities/tests/test_data/ruby/sinatra/CVE-2018-11627.yml
rename to vulnerabilities/tests/test_data/ruby/CVE-2018-11627.yml
diff --git a/vulnerabilities/tests/test_data/ruby/CVE-2018-7212-expected.json b/vulnerabilities/tests/test_data/ruby/CVE-2018-7212-expected.json
new file mode 100644
index 000000000..a8d31bd5f
--- /dev/null
+++ b/vulnerabilities/tests/test_data/ruby/CVE-2018-7212-expected.json
@@ -0,0 +1,48 @@
+{
+ "aliases": [
+ "CVE-2018-7212"
+ ],
+ "summary": "sinatra ruby gem path traversal via backslash characters on Windows\nAn issue was discovered in rack-protection/lib/rack/protection/path_traversal.rb\nin Sinatra 2.x before 2.0.1 on Windows. Path traversal is possible via backslash\ncharacters.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:gem/<2.0.1",
+ "fixed_version": null
+ },
+ {
+ "package": {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:gem/>1.0.0",
+ "fixed_version": null
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv3",
+ "value": "5.3",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2018-01-09T00:00:00+00:00",
+ "weaknesses": [],
+ "url": "https://github.com/rubysec/ruby-advisory-db"
+}
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/ruby/sinatra/CVE-2018-7212.yml b/vulnerabilities/tests/test_data/ruby/CVE-2018-7212.yml
similarity index 100%
rename from vulnerabilities/tests/test_data/ruby/sinatra/CVE-2018-7212.yml
rename to vulnerabilities/tests/test_data/ruby/CVE-2018-7212.yml
diff --git a/vulnerabilities/tests/test_data/ruby/parse-advisory-ruby-expected.json b/vulnerabilities/tests/test_data/ruby/parse-advisory-ruby-expected.json
new file mode 100644
index 000000000..75f0dd4ad
--- /dev/null
+++ b/vulnerabilities/tests/test_data/ruby/parse-advisory-ruby-expected.json
@@ -0,0 +1,60 @@
+[
+ {
+ "aliases": [
+ "CVE-2018-7212"
+ ],
+ "summary": "sinatra ruby gem path traversal via backslash characters on Windows\nAn issue was discovered in rack-protection/lib/rack/protection/path_traversal.rb\nin Sinatra 2.x before 2.0.1 on Windows. Path traversal is possible via backslash\ncharacters.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:gem/<2.0.1",
+ "fixed_version": null
+ },
+ {
+ "package": {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:gem/>1.0.0",
+ "fixed_version": null
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv2",
+ "value": "5.0",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv3",
+ "value": "5.3",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "date_published": "2018-01-09T00:00:00+00:00",
+ "weaknesses": []
+}
+]
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/ruby/ruby-improver-expected.json b/vulnerabilities/tests/test_data/ruby/ruby-improver-expected.json
new file mode 100644
index 000000000..a17ae5f00
--- /dev/null
+++ b/vulnerabilities/tests/test_data/ruby/ruby-improver-expected.json
@@ -0,0 +1,215 @@
+[
+ {
+ "vulnerability_id": null,
+ "aliases": [
+ "CVE-2018-7212"
+ ],
+ "confidence": 100,
+ "summary": "sinatra ruby gem path traversal via backslash characters on Windows\nAn issue was discovered in rack-protection/lib/rack/protection/path_traversal.rb\nin Sinatra 2.x before 2.0.1 on Windows. Path traversal is possible via backslash\ncharacters.",
+ "affected_purls": [
+ {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": "0.2.6",
+ "qualifiers": null,
+ "subpath": null
+ },
+ {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": "1.2.7",
+ "qualifiers": null,
+ "subpath": null
+ },
+ {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": "1.3.6",
+ "qualifiers": null,
+ "subpath": null
+ }
+ ],
+ "fixed_purl": {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": "2.2.1",
+ "qualifiers": null,
+ "subpath": null
+ },
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv2",
+ "value": "5.0",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv3",
+ "value": "5.3",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "weaknesses": []
+ },
+ {
+ "vulnerability_id": null,
+ "aliases": [
+ "CVE-2018-7212"
+ ],
+ "confidence": 100,
+ "summary": "sinatra ruby gem path traversal via backslash characters on Windows\nAn issue was discovered in rack-protection/lib/rack/protection/path_traversal.rb\nin Sinatra 2.x before 2.0.1 on Windows. Path traversal is possible via backslash\ncharacters.",
+ "affected_purls": [
+ {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": "1.2.7",
+ "qualifiers": null,
+ "subpath": null
+ },
+ {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": "1.3.6",
+ "qualifiers": null,
+ "subpath": null
+ },
+ {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": "2.2.1",
+ "qualifiers": null,
+ "subpath": null
+ },
+ {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": "3.0.2",
+ "qualifiers": null,
+ "subpath": null
+ },
+ {
+ "type": "gem",
+ "namespace": null,
+ "name": "sinatra",
+ "version": "3.0.5",
+ "qualifiers": null,
+ "subpath": null
+ }
+ ],
+ "fixed_purl": null,
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv2",
+ "value": "5.0",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv3",
+ "value": "5.3",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "weaknesses": []
+ },
+ {
+ "vulnerability_id": null,
+ "aliases": [
+ "CVE-2018-7212"
+ ],
+ "confidence": 100,
+ "summary": "sinatra ruby gem path traversal via backslash characters on Windows\nAn issue was discovered in rack-protection/lib/rack/protection/path_traversal.rb\nin Sinatra 2.x before 2.0.1 on Windows. Path traversal is possible via backslash\ncharacters.",
+ "affected_purls": [],
+ "fixed_purl": null,
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv2",
+ "value": "5.0",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv3",
+ "value": "5.3",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "weaknesses": []
+ },
+ {
+ "vulnerability_id": null,
+ "aliases": [
+ "CVE-2018-7212"
+ ],
+ "confidence": 100,
+ "summary": "sinatra ruby gem path traversal via backslash characters on Windows\nAn issue was discovered in rack-protection/lib/rack/protection/path_traversal.rb\nin Sinatra 2.x before 2.0.1 on Windows. Path traversal is possible via backslash\ncharacters.",
+ "affected_purls": [],
+ "fixed_purl": null,
+ "references": [
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv2",
+ "value": "5.0",
+ "scoring_elements": ""
+ }
+ ]
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/sinatra/sinatra/pull/1379",
+ "severities": [
+ {
+ "system": "cvssv3",
+ "value": "5.3",
+ "scoring_elements": ""
+ }
+ ]
+ }
+ ],
+ "weaknesses": []
+ }
+]
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/ruby/sidekiq/OSVDB-125675.yml b/vulnerabilities/tests/test_data/ruby/sidekiq/OSVDB-125675.yml
deleted file mode 100644
index 12e317da0..000000000
--- a/vulnerabilities/tests/test_data/ruby/sidekiq/OSVDB-125675.yml
+++ /dev/null
@@ -1,9 +0,0 @@
----
-gem: sidekiq
-osvdb: 125675
-url: https://github.com/mperham/sidekiq/pull/2422
-title: Sidekiq Gem for Ruby Multiple Unspecified CSRF
-date: 2015-07-06
-description: Sidekiq::Web lacks CSRF protection
-patched_versions:
- - ">= 3.4.2"
diff --git a/vulnerabilities/tests/test_data/ruby/sidekiq/OSVDB-125676.yml b/vulnerabilities/tests/test_data/ruby/sidekiq/OSVDB-125676.yml
deleted file mode 100644
index 18ba94428..000000000
--- a/vulnerabilities/tests/test_data/ruby/sidekiq/OSVDB-125676.yml
+++ /dev/null
@@ -1,14 +0,0 @@
----
-gem: sidekiq
-osvdb: 125676
-url: https://github.com/mperham/sidekiq/issues/2330
-title: |
- Sidekiq Gem for Ruby web/views/queue.erb CurrentMessagesInQueue Element
- Reflected XSS
-date: 2015-06-04
-description: XSS via queue name in Sidekiq::Web
-patched_versions:
- - ">= 3.4.0"
-related:
- osvdb:
- - 125677
diff --git a/vulnerabilities/tests/test_data/ruby/sidekiq/OSVDB-125678.yml b/vulnerabilities/tests/test_data/ruby/sidekiq/OSVDB-125678.yml
deleted file mode 100644
index 1566d10a7..000000000
--- a/vulnerabilities/tests/test_data/ruby/sidekiq/OSVDB-125678.yml
+++ /dev/null
@@ -1,9 +0,0 @@
----
-gem: sidekiq
-osvdb: 125678
-url: https://github.com/mperham/sidekiq/pull/2309
-title: Sidekiq Gem for Ruby web/views/queue.erb msg.display_class Element XSS
-date: 2015-04-21
-description: XSS via job arguments display class in Sidekiq::Web
-patched_versions:
- - ">= 3.4.0"
diff --git a/vulnerabilities/tests/test_data_source.py b/vulnerabilities/tests/test_data_source.py
index 369ac9c23..7d0a5f707 100644
--- a/vulnerabilities/tests/test_data_source.py
+++ b/vulnerabilities/tests/test_data_source.py
@@ -21,12 +21,14 @@
from vulnerabilities.importers.elixir_security import ElixirSecurityImporter
from vulnerabilities.importers.fireeye import FireyeImporter
from vulnerabilities.importers.gentoo import GentooImporter
+from vulnerabilities.importers.github_osv import GithubOSVImporter
from vulnerabilities.importers.gitlab import GitLabAPIImporter
from vulnerabilities.importers.istio import IstioImporter
from vulnerabilities.importers.mozilla import MozillaImporter
from vulnerabilities.importers.npm import NpmImporter
from vulnerabilities.importers.pypa import PyPaImporter
from vulnerabilities.importers.retiredotnet import RetireDotnetImporter
+from vulnerabilities.importers.ruby import RubyImporter
from vulnerabilities.oval_parser import OvalParser
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -123,6 +125,8 @@ def test_git_importer(mock_clone):
NpmImporter,
RetireDotnetImporter,
PyPaImporter,
+ RubyImporter,
+ GithubOSVImporter,
],
)
def test_git_importer_clone(git_importer):
diff --git a/vulnerabilities/tests/test_fireeye.py b/vulnerabilities/tests/test_fireeye.py
index f6a5be74a..15935728c 100644
--- a/vulnerabilities/tests/test_fireeye.py
+++ b/vulnerabilities/tests/test_fireeye.py
@@ -172,3 +172,48 @@ def test_parse_advisory_data_2(self):
result = imported_data.to_dict()
util_tests.check_results_against_json(result, expected_file)
+
+ def test_md_list_to_dict_2(self):
+ expected_output = {
+ "# MNDT-2023-0017\n": [
+ "\n",
+ "The IBM Personal Communications (PCOMM) application 13.0.0 and earlier caused a user's plaintext password to be written to the `C:\\Temp\\pcsnp_init.log` file when re-connection was made through a remote desktop protocol.\n",
+ "\n",
+ ],
+ "## Common Weakness Enumeration\n": [
+ "CWE-312: Cleartext Storage of Sensitive Information\n",
+ "\n",
+ ],
+ "## Impact\n": [
+ "High - An attacker with low-privilege access to a host with IBM PCOMM could recover the plaintext password of another user.\n",
+ "\n",
+ ],
+ "## Exploitability\n": [
+ "Low - Exploitability varies depending on the environment in which IBM PCOMM is installed. Mandiant identified this vulnerability when conducting independent security research for a client that used Citrix to connect to shared Windows Server instances. In certain environments where remote desktop is used to connect to shared hosts with IBM PCOMM installed, the exploitability is greatly increased.\n",
+ "\n",
+ ],
+ "## CVE Reference\n": ["CVE-2016-0321 - scope expanded\n", "\n"],
+ "## Technical Details\n": [
+ "While conducting independent security research, Mandiant identified a plaintext Active Directory password stored within the `C:\\Temp\\pcsnp_init.log` file. The affected host had IBM PCOMM version 13.0.0 installed and was used by multiple users who connected with Citrix. Upon a user connecting, disconnecting, and connecting again, the user's plaintext password was stored in the `C:\\Temp\\pcsnp_init.log` file.\n",
+ "\n",
+ ],
+ "## Discovery Credits\n": [
+ "- Adin Drabkin, Mandiant\n",
+ "- Matthew Rotlevi, Mandiant\n",
+ "\n",
+ ],
+ "## Disclosure Timeline\n": [
+ "- 2023-09-26 - Issue reported to the vendor.\n",
+ "- 2023-11-03 - The vendor updated the security bulletin for CVE-2016-0321 to include all known affected and fixed versions.\n",
+ "\n",
+ ],
+ "## References\n": [
+ "- [IBM Security Bulletin](https://www.ibm.com/support/pages/security-bulletin-ibm-personal-communications-could-allow-remote-user-obtain-sensitive-information-including-user-passwords-allowing-unauthorized-access-cve-2016-0321)\n",
+ "- [IBM Personal Communications](https://www.ibm.com/support/pages/ibm-personal-communications)\n",
+ "- [Mitre CVE-2016-0321](https://www.cve.org/CVERecord?id=CVE-2016-0321)\n",
+ ],
+ }
+ with open(os.path.join(TEST_DATA, "fireeye_test3.md"), encoding="utf-8-sig") as f:
+ md_list = f.readlines()
+ md_dict = md_list_to_dict(md_list)
+ assert md_dict == expected_output
diff --git a/vulnerabilities/tests/test_get_serverity.py b/vulnerabilities/tests/test_get_serverity.py
new file mode 100644
index 000000000..4ac3e646f
--- /dev/null
+++ b/vulnerabilities/tests/test_get_serverity.py
@@ -0,0 +1,100 @@
+import pytest
+from cvss.exceptions import CVSS2MalformedError
+from cvss.exceptions import CVSS3MalformedError
+
+from vulnerabilities.severity_systems import CVSSV2
+from vulnerabilities.severity_systems import CVSSV3
+from vulnerabilities.templatetags.show_cvss import cvss_printer
+
+
+def test_get_cvss2_vector_values():
+ assert (
+ CVSSV2.get("AV:N/AC:L/Au:N/C:P/I:N/A:N ")
+ == CVSSV2.get("AV:N/AC:L/Au:N/C:P/I:N/A:N")
+ == {
+ "accessComplexity": "LOW",
+ "accessVector": "NETWORK",
+ "authentication": "NONE",
+ "availabilityImpact": "NONE",
+ "availabilityRequirement": "NOT_DEFINED",
+ "baseScore": 5.0,
+ "collateralDamagePotential": "NOT_DEFINED",
+ "confidentialityImpact": "PARTIAL",
+ "confidentialityRequirement": "NOT_DEFINED",
+ "environmentalScore": 0.0,
+ "exploitability": "NOT_DEFINED",
+ "integrityImpact": "NONE",
+ "integrityRequirement": "NOT_DEFINED",
+ "remediationLevel": "NOT_DEFINED",
+ "reportConfidence": "NOT_DEFINED",
+ "targetDistribution": "NOT_DEFINED",
+ "temporalScore": 0.0,
+ "vectorString": "AV:N/AC:L/Au:N/C:P/I:N/A:N",
+ "version": "2.0",
+ }
+ )
+
+ with pytest.raises(CVSS2MalformedError):
+ CVSSV2.get("")
+
+ with pytest.raises(CVSS2MalformedError):
+ CVSSV2.get("AV:N/AffgL/Au:N/C:P/I:N/A:N ")
+
+
+def test_get_cvss3_vector_values():
+ assert (
+ CVSSV3.get("CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H ")
+ == CVSSV3.get("CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H")
+ == {
+ "attackComplexity": "LOW",
+ "attackVector": "NETWORK",
+ "availabilityImpact": "HIGH",
+ "availabilityRequirement": "NOT_DEFINED",
+ "baseScore": 9.1,
+ "baseSeverity": "CRITICAL",
+ "confidentialityImpact": "HIGH",
+ "confidentialityRequirement": "NOT_DEFINED",
+ "environmentalScore": 9.1,
+ "environmentalSeverity": "CRITICAL",
+ "exploitCodeMaturity": "NOT_DEFINED",
+ "integrityImpact": "HIGH",
+ "integrityRequirement": "NOT_DEFINED",
+ "modifiedAttackComplexity": "LOW",
+ "modifiedAttackVector": "NETWORK",
+ "modifiedAvailabilityImpact": "HIGH",
+ "modifiedConfidentialityImpact": "HIGH",
+ "modifiedIntegrityImpact": "HIGH",
+ "modifiedPrivilegesRequired": "HIGH",
+ "modifiedScope": "CHANGED",
+ "modifiedUserInteraction": "NONE",
+ "privilegesRequired": "HIGH",
+ "remediationLevel": "NOT_DEFINED",
+ "reportConfidence": "NOT_DEFINED",
+ "scope": "CHANGED",
+ "temporalScore": 9.1,
+ "temporalSeverity": "CRITICAL",
+ "userInteraction": "NONE",
+ "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H",
+ "version": "3.1",
+ }
+ )
+
+ with pytest.raises(CVSS3MalformedError):
+ CVSSV3.get("CVSS:3.7/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H ")
+
+ with pytest.raises(CVSS3MalformedError):
+ CVSSV3.get("")
+
+
+def test_blank_cvss_printer():
+ result = cvss_printer("", "")
+ assert result == ""
+
+
+def test_cvss_printer():
+ result = cvss_printer("HIGH", "high,medium,low")
+ assert result == (
+ "
high
"
+ "
medium
"
+ "
low
"
+ )
diff --git a/vulnerabilities/tests/test_github_osv.py b/vulnerabilities/tests/test_github_osv.py
new file mode 100644
index 000000000..559ba8d15
--- /dev/null
+++ b/vulnerabilities/tests/test_github_osv.py
@@ -0,0 +1,113 @@
+#
+# 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/github_osv")
+
+
+class GithubOSVImporter(TestCase):
+ def test_github_osv_importer1(self):
+ with open(os.path.join(TEST_DATA, "github_osv_test_1.json")) as f:
+ mock_response = json.load(f)
+ expected_file = os.path.join(TEST_DATA, "github_osv_expected_1.json")
+ imported_data = parse_advisory_data(
+ mock_response,
+ supported_ecosystems=["npm"],
+ advisory_url="https://github.com/github/advisory-database"
+ "/blob/main/advisories/github-reviewed/github_osv_test_1.json",
+ )
+ result = imported_data.to_dict()
+ util_tests.check_results_against_json(result, expected_file)
+
+ def test_github_osv_importer2(self):
+ with open(os.path.join(TEST_DATA, "github_osv_test_2.json")) as f:
+ mock_response = json.load(f)
+ expected_file = os.path.join(TEST_DATA, "github_osv_expected_2.json")
+ # if supported_ecosystems = [] : the expected affected_packages = []
+ imported_data = parse_advisory_data(
+ mock_response,
+ supported_ecosystems=[],
+ advisory_url="https://github.com/github/advisory-database"
+ "/blob/main/advisories/github-reviewed/github_osv_test_2.json",
+ )
+ result = imported_data.to_dict()
+ util_tests.check_results_against_json(result, expected_file)
+
+ def test_github_osv_importer3(self):
+ with open(os.path.join(TEST_DATA, "github_osv_test_3.json")) as f:
+ mock_response = json.load(f)
+ expected_file = os.path.join(TEST_DATA, "github_osv_expected_3.json")
+ imported_data = parse_advisory_data(
+ mock_response,
+ supported_ecosystems=["maven"],
+ advisory_url="https://github.com/github/advisory-database"
+ "/blob/main/advisories/github-reviewed/github_osv_test_3.json",
+ )
+ result = imported_data.to_dict()
+ util_tests.check_results_against_json(result, expected_file)
+
+ def test_github_osv_importer4(self):
+ with open(os.path.join(TEST_DATA, "github_osv_test_4.json")) as f:
+ mock_response = json.load(f)
+ expected_file = os.path.join(TEST_DATA, "github_osv_expected_4.json")
+ imported_data = parse_advisory_data(
+ mock_response,
+ supported_ecosystems=["gem"],
+ advisory_url="https://github.com/github/advisory-database"
+ "/blob/main/advisories/github-reviewed/github_osv_test_4.json",
+ )
+ result = imported_data.to_dict()
+ util_tests.check_results_against_json(result, expected_file)
+
+ def test_github_osv_importer5(self):
+ # test golang
+ with open(os.path.join(TEST_DATA, "github_osv_test_5.json")) as f:
+ mock_response = json.load(f)
+ expected_file = os.path.join(TEST_DATA, "github_osv_expected_5.json")
+ imported_data = parse_advisory_data(
+ mock_response,
+ supported_ecosystems=["golang"],
+ advisory_url="https://github.com/github/advisory-database"
+ "/blob/main/advisories/github-reviewed/github_osv_test_5.json",
+ )
+ result = imported_data.to_dict()
+ util_tests.check_results_against_json(result, expected_file)
+
+ def test_github_osv_importer6(self):
+ # test golang
+ with open(os.path.join(TEST_DATA, "github_osv_test_6.json")) as f:
+ mock_response = json.load(f)
+ expected_file = os.path.join(TEST_DATA, "github_osv_expected_6.json")
+ imported_data = parse_advisory_data(
+ mock_response,
+ supported_ecosystems=["golang"],
+ advisory_url="https://github.com/github/advisory-database"
+ "/blob/main/advisories/github-reviewed/github_osv_test_6.json",
+ )
+ result = imported_data.to_dict()
+ util_tests.check_results_against_json(result, expected_file)
+
+ def test_github_osv_importer7(self):
+ with open(os.path.join(TEST_DATA, "github_osv_test_7.json")) as f:
+ mock_response = json.load(f)
+ expected_file = os.path.join(TEST_DATA, "github_osv_expected_7.json")
+ imported_data = parse_advisory_data(
+ mock_response,
+ supported_ecosystems=["nuget"],
+ advisory_url="https://github.com/github/advisory-database"
+ "/blob/main/advisories/github-reviewed/github_osv_test_7.json",
+ )
+ result = imported_data.to_dict()
+ util_tests.check_results_against_json(result, expected_file)
diff --git a/vulnerabilities/tests/test_models.py b/vulnerabilities/tests/test_models.py
index ed8eb29e6..2efe45e86 100644
--- a/vulnerabilities/tests/test_models.py
+++ b/vulnerabilities/tests/test_models.py
@@ -407,8 +407,8 @@ def test_univers_version_class(self):
pypi_package_version = RANGE_CLASS_BY_SCHEMES[pypi_package.type].version_class
assert pypi_package_version == versions.PypiVersion
- RANGE_CLASS_BY_SCHEMES["alpine"] = AlpineLinuxVersionRange
- alpine_version = RANGE_CLASS_BY_SCHEMES["alpine"].version_class
+ alpine_package = models.Package.objects.create(type="alpine", name="lxml", version="0.9")
+ alpine_version = RANGE_CLASS_BY_SCHEMES[alpine_package.type].version_class
assert alpine_version == versions.AlpineLinuxVersion
def test_sort_by_version(self):
diff --git a/vulnerabilities/tests/test_osv.py b/vulnerabilities/tests/test_osv.py
index 3ca50cebf..5779d0589 100644
--- a/vulnerabilities/tests/test_osv.py
+++ b/vulnerabilities/tests/test_osv.py
@@ -13,6 +13,7 @@
from univers.version_constraint import VersionConstraint
from univers.version_range import PypiVersionRange
from univers.versions import PypiVersion
+from univers.versions import SemverVersion
from vulnerabilities.importer import Reference
from vulnerabilities.importer import VulnerabilitySeverity
@@ -353,12 +354,18 @@ def test_get_affected_version_range(self):
assert results == expected
def test_get_fixed_versions1(self):
- assert get_fixed_versions(fixed_range={}, raw_id="GHSA-j3f7-7rmc-6wqj") == []
+ assert (
+ get_fixed_versions(
+ fixed_range={}, raw_id="GHSA-j3f7-7rmc-6wqj", supported_ecosystem="pypi"
+ )
+ == []
+ )
def test_get_fixed_versions2(self):
results = get_fixed_versions(
fixed_range={"type": "ECOSYSTEM", "events": [{"introduced": "0"}, {"fixed": "1.7.0"}]},
raw_id="GHSA-j3f7-7rmc-6wqj",
+ supported_ecosystem="pypi",
)
assert results == [PypiVersion("1.7.0")]
@@ -374,6 +381,19 @@ def test_get_fixed_versions3(self):
],
},
raw_id="GHSA-j3f7-7rmc-6wqj",
+ supported_ecosystem="pypi",
)
assert results == [PypiVersion("9.0.0"), PypiVersion("9.0.1")]
+
+ def test_get_fixed_versions4(self):
+ results = get_fixed_versions(
+ fixed_range={
+ "type": "ECOSYSTEM",
+ "events": [{"introduced": "0"}, {"fixed": "6.5.4"}],
+ },
+ raw_id="GHSA-r9p9-mrjm-926w",
+ supported_ecosystem="npm",
+ )
+
+ assert results == [SemverVersion("6.5.4")]
diff --git a/vulnerabilities/tests/test_pypa.py b/vulnerabilities/tests/test_pypa.py
index ffd648fac..1a59260e6 100644
--- a/vulnerabilities/tests/test_pypa.py
+++ b/vulnerabilities/tests/test_pypa.py
@@ -22,9 +22,11 @@ class TestPyPaImporter(TestCase):
def test_to_advisories_with_summary(self):
with open(os.path.join(TEST_DATA, "pypa_test.yaml")) as f:
mock_response = saneyaml.load(f)
- expected_file = os.path.join(TEST_DATA, f"pypa-expected.json")
+ expected_file = os.path.join(TEST_DATA, "pypa-expected.json")
imported_data = parse_advisory_data(
- mock_response, "pypi", "https://github.com/pypa/advisory-database"
+ mock_response,
+ ["pypi"],
+ "https://github.com/pypa/advisory-database/blob/main/vulns/pypa-expected.json",
)
result = imported_data.to_dict()
util_tests.check_results_against_json(result, expected_file)
diff --git a/vulnerabilities/tests/test_pysec.py b/vulnerabilities/tests/test_pysec.py
index f12a6e417..dcba3a776 100644
--- a/vulnerabilities/tests/test_pysec.py
+++ b/vulnerabilities/tests/test_pysec.py
@@ -22,7 +22,7 @@ class TestPyPIImporter(TestCase):
def test_to_advisories_with_summary(self):
with open(os.path.join(TEST_DATA, "pysec-advisories_with_summary.json")) as f:
mock_response = json.load(f)
- results = parse_advisory_data(mock_response, "pypi", "https://test.com").to_dict()
+ results = parse_advisory_data(mock_response, ["pypi"], "https://test.com").to_dict()
expected_file = os.path.join(TEST_DATA, "pysec-advisories_with_summary-expected.json")
check_results_against_json(
@@ -35,7 +35,7 @@ def test_to_advisories_without_summary(self):
with open(os.path.join(TEST_DATA, "pysec-advisories_without_summary.json")) as f:
mock_response = json.load(f)
- results = parse_advisory_data(mock_response, "pypi", "https://test.com").to_dict()
+ results = parse_advisory_data(mock_response, ["pypi"], "https://test.com").to_dict()
expected_file = os.path.join(TEST_DATA, "pysec-advisories_without_summary-expected.json")
check_results_against_json(
@@ -49,7 +49,7 @@ def test_to_advisories_with_cwe(self):
mock_response = json.load(f)
results = parse_advisory_data(
- raw_data=mock_response, supported_ecosystem="pypi", advisory_url="https://tes.com"
+ raw_data=mock_response, supported_ecosystems=["pypi"], advisory_url="https://tes.com"
).to_dict()
expected_file = os.path.join(TEST_DATA, "pysec-advisories_with_cwe-expected.json")
diff --git a/vulnerabilities/tests/test_ruby.py b/vulnerabilities/tests/test_ruby.py
index e57026fe3..0e06afe1d 100644
--- a/vulnerabilities/tests/test_ruby.py
+++ b/vulnerabilities/tests/test_ruby.py
@@ -6,135 +6,91 @@
# 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
-import pathlib
-from unittest import TestCase
from unittest.mock import patch
+import pytest
from packageurl import PackageURL
+from univers.version_range import GemVersionRange
from vulnerabilities.importer import AdvisoryData
-from vulnerabilities.importer import Reference
-from vulnerabilities.importers.ruby import RubyImporter
-from vulnerabilities.package_managers import RubyVersionAPI
-from vulnerabilities.package_managers import VersionResponse
-from vulnerabilities.utils import AffectedPackage
+from vulnerabilities.importer import AffectedPackage
+from vulnerabilities.importers.ruby import get_affected_packages
+from vulnerabilities.importers.ruby import parse_ruby_advisory
+from vulnerabilities.improvers.default import DefaultImprover
+from vulnerabilities.improvers.valid_versions import RubyImprover
+from vulnerabilities.tests import util_tests
+from vulnerabilities.tests.util_tests import check_results_against_json
+from vulnerabilities.utils import load_yaml
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
TEST_DATA = os.path.join(BASE_DIR, "test_data", "ruby")
-MOCK_ADDED_FILES = []
-
-for filepath in pathlib.Path(TEST_DATA).glob("**/*.yml"):
- MOCK_ADDED_FILES.append(filepath.absolute())
+@pytest.mark.parametrize(
+ "filename,expected_filename,schema_type",
+ [
+ ("CVE-2018-7212.yml", "CVE-2018-7212-expected.json", "gems"),
+ ("CVE-2018-11627.yml", "CVE-2018-11627-expected.json", "gems"),
+ ("CVE-2007-5770.yml", "CVE-2007-5770-expected.json", "rubies"),
+ ("CVE-2010-1330.yml", "CVE-2010-1330-expected.json", "rubies"),
+ ],
+)
+def test_advisories(filename, expected_filename, schema_type):
+ file_path = os.path.join(TEST_DATA, filename)
+ mock_response = load_yaml(file_path)
+ results = parse_ruby_advisory(
+ mock_response, schema_type, "https://github.com/rubysec/ruby-advisory-db"
+ ).to_dict()
+ expected_file = os.path.join(TEST_DATA, expected_filename)
+ check_results_against_json(results=results, expected_file=expected_file)
-class RubyImporterTest(TestCase):
- @classmethod
- def setUpClass(cls):
- data_source_cfg = {
- "repository_url": "https://github.com/rubysec/ruby-advisory-db.git",
- }
- cls.data_src = RubyImporter(1, config=data_source_cfg)
- cls.data_src.pkg_manager_api = RubyVersionAPI()
-
- @patch(
- "vulnerabilities.package_managers.RubyVersionAPI.get",
- return_value=VersionResponse(
- valid_versions={"1.0.0", "1.8.0", "2.0.3"}, newer_versions=set()
- ),
- )
- def test_process_file(self, mock_write):
- expected_advisories = [
- Advisory(
- summary="An issue was discovered in rack-protection/lib/rack/protection/path_traversal.rb\nin Sinatra 2.x before 2.0.1 on Windows. Path traversal is possible via backslash\ncharacters.\n",
- vulnerability_id="CVE-2018-7212",
- affected_packages=[
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="gem",
- namespace=None,
- name="sinatra",
- version="1.8.0",
- ),
- patched_package=PackageURL(
- type="gem",
- namespace=None,
- name="sinatra",
- version="2.0.3",
- ),
- )
- ],
- references=[
- Reference(
- reference_id="",
- url="https://github.com/sinatra/sinatra/pull/1379",
- severities=[],
- )
- ],
- ),
- Advisory(
- summary="Sinatra before 2.0.2 has XSS via the 400 Bad Request page that occurs upon a params parser exception.\n",
- vulnerability_id="CVE-2018-11627",
- affected_packages=[
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="gem",
- namespace=None,
- name="sinatra",
- version="1.0.0",
- ),
- patched_package=PackageURL(
- type="gem",
- namespace=None,
- name="sinatra",
- version="2.0.3",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="gem",
- namespace=None,
- name="sinatra",
- version="1.8.0",
- ),
- patched_package=PackageURL(
- type="gem",
- namespace=None,
- name="sinatra",
- version="2.0.3",
- ),
- ),
- ],
- references=[
- Reference(
- reference_id="",
- url="https://github.com/sinatra/sinatra/issues/1428",
- severities=[],
- )
- ],
- ),
- ]
- found_advisories = []
- for p in MOCK_ADDED_FILES:
- advisory = self.data_src.process_file(p)
- if advisory:
- found_advisories.append(advisory)
- found_advisories = list(map(Advisory.normalized, found_advisories))
- expected_advisories = list(map(Advisory.normalized, expected_advisories))
- assert sorted(found_advisories) == sorted(expected_advisories)
+@patch("vulnerabilities.improvers.valid_versions.RubyImprover.get_package_versions")
+def test_ruby_improver(mock_response):
+ advisory_file = os.path.join(TEST_DATA, f"parse-advisory-ruby-expected.json")
+ with open(advisory_file) as exp:
+ advisories = [AdvisoryData.from_dict(adv) for adv in (json.load(exp))]
+ mock_response.return_value = ["0.2.6", "1.2.7", "1.3.6", "2.2.1", "3.0.2", "3.0.5"]
+ improvers = [RubyImprover(), DefaultImprover()]
+ result = []
+ for improver in improvers:
+ for advisory in advisories:
+ inference = [data.to_dict() for data in improver.get_inferences(advisory)]
+ result.extend(inference)
+ expected_file = os.path.join(TEST_DATA, f"ruby-improver-expected.json")
+ util_tests.check_results_against_json(result, expected_file)
- def test_categorize_versions(self):
- all_versions = ["1.0.0", "1.2.0", "9.0.2", "0.2.3"]
- safe_ver_ranges = ["==1.0.0", ">1.2.0"]
-
- exp_safe_vers = ["1.0.0", "9.0.2"]
- exp_aff_vers = ["1.2.0", "0.2.3"]
-
- safe_vers, aff_vers = self.data_src.categorize_versions(all_versions, safe_ver_ranges)
- assert exp_aff_vers == aff_vers
- assert exp_safe_vers == safe_vers
+@pytest.mark.parametrize(
+ "record,purl,result",
+ [
+ (
+ {"patched_versions": [">= 1.6.5.1"]},
+ PackageURL(type="gem", name="jruby"),
+ [
+ AffectedPackage(
+ package=PackageURL(type="gem", name="jruby"),
+ affected_version_range=GemVersionRange.from_string("vers:gem/<1.6.5.1"),
+ )
+ ],
+ ),
+ (
+ {"patched_versions": [">= 1.1.3"], "unaffected_versions": ["< 0.1.33"]},
+ PackageURL(type="gem", name="'devise_token_auth'"),
+ [
+ AffectedPackage(
+ package=PackageURL(type="gem", name="'devise_token_auth'"),
+ affected_version_range=GemVersionRange.from_string("vers:gem/<1.1.3"),
+ ),
+ AffectedPackage(
+ package=PackageURL(type="gem", name="'devise_token_auth'"),
+ affected_version_range=GemVersionRange.from_string("vers:gem/>=0.1.33"),
+ ),
+ ],
+ ),
+ ],
+)
+def test_get_affected_packages(record, purl, result):
+ assert get_affected_packages(record, purl) == result
diff --git a/vulnerabilities/views.py b/vulnerabilities/views.py
index 026ce1b09..391c165e7 100644
--- a/vulnerabilities/views.py
+++ b/vulnerabilities/views.py
@@ -6,9 +6,11 @@
# See https://github.com/nexB/vulnerablecode for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#
-
+import logging
from datetime import datetime
+from cvss.exceptions import CVSS2MalformedError
+from cvss.exceptions import CVSS3MalformedError
from django.contrib import messages
from django.core.exceptions import ValidationError
from django.core.mail import send_mail
@@ -26,6 +28,7 @@
from vulnerabilities.forms import PackageSearchForm
from vulnerabilities.forms import VulnerabilitySearchForm
from vulnerabilities.models import VulnerabilityStatusType
+from vulnerabilities.severity_systems import SCORING_SYSTEMS
from vulnerabilities.utils import get_severity_range
from vulnerablecode.settings import env
@@ -132,6 +135,16 @@ def get_context_data(self, **kwargs):
weakness_object for weakness_object in weaknesses if weakness_object.weakness
]
status = self.object.get_status_label
+
+ severity_vectors = []
+ for s in self.object.severities:
+ if s.scoring_elements and s.scoring_system in SCORING_SYSTEMS:
+ try:
+ vector_values = SCORING_SYSTEMS[s.scoring_system].get(s.scoring_elements)
+ severity_vectors.append(vector_values)
+ except (CVSS2MalformedError, CVSS3MalformedError, NotImplementedError):
+ logging.error(f"CVSSMalformedError for {s.scoring_elements}")
+
context.update(
{
"vulnerability": self.object,
@@ -140,6 +153,7 @@ def get_context_data(self, **kwargs):
"severity_score_range": get_severity_range(
{s.value for s in self.object.severities}
),
+ "severity_vectors": severity_vectors,
"references": self.object.references.all(),
"aliases": self.object.aliases.all(),
"affected_packages": self.object.affected_packages.all(),
diff --git a/vulnerablecode/__init__.py b/vulnerablecode/__init__.py
index b0bd1606d..e4d5b5f8d 100644
--- a/vulnerablecode/__init__.py
+++ b/vulnerablecode/__init__.py
@@ -12,7 +12,7 @@
import warnings
from pathlib import Path
-__version__ = "34.0.0rc1"
+__version__ = "34.0.0rc4"
def command_line():
diff --git a/vulntotal/datasources/deps.py b/vulntotal/datasources/deps.py
index 33c62773d..413c0d18b 100644
--- a/vulntotal/datasources/deps.py
+++ b/vulntotal/datasources/deps.py
@@ -26,12 +26,21 @@ class DepsDataSource(DataSource):
def fetch_json_response(self, url):
response = requests.get(url)
- if not response.status_code == 200 or response.text == "Not Found":
+ if response.status_code != 200 or response.text == "Not Found":
logger.error(f"Error while fetching {url}")
return
return response.json()
def datasource_advisory(self, purl) -> Iterable[VendorData]:
+ """
+ Fetch and parse advisories from a given purl.
+
+ Parameters:
+ purl: A string representing the package URL.
+
+ Returns:
+ A list of VendorData objects containing the advisory information.
+ """
payload = generate_meta_payload(purl)
response = self.fetch_json_response(payload)
if response:
@@ -58,6 +67,16 @@ def supported_ecosystem(cls):
def parse_advisory(advisory, purl) -> Iterable[VendorData]:
+ """
+ Parse an advisory into a VendorData object.
+
+ Parameters:
+ advisory: A dictionary representing the advisory data.
+ purl: PURL for the advisory.
+
+ Yields:
+ VendorData instance containing purl, aliases, affected_versions and fixed_versions.
+ """
package = advisory["packages"][0]
affected_versions = [event["version"] for event in package["versionsAffected"]]
fixed_versions = [event["version"] for event in package["versionsUnaffected"]]
@@ -70,6 +89,15 @@ def parse_advisory(advisory, purl) -> Iterable[VendorData]:
def parse_advisories_from_meta(advisories_metadata):
+ """
+ Parse advisories from a given metadata.
+
+ Parameters:
+ advisories_metadata: A dictionary representing the metadata of the advisories.
+
+ Returns:
+ A list of dictionaries, each representing an advisory.
+ """
advisories = []
dependencies = advisories_metadata.get("dependencies") or []
for dependency in dependencies:
@@ -84,6 +112,15 @@ def generate_advisory_payload(advisory_meta):
def generate_meta_payload(purl):
+ """
+ Generate a payload for fetching advisories metadata from a given purl.
+
+ Parameters:
+ purl: A PackageURL object representing the package URL.
+
+ Returns:
+ A string representing the payload for fetching advisories metadata. It should be a valid URL that contains the ecosystem, package name and package version of the dependency.
+ """
url_advisories_meta = "https://deps.dev/_/s/{ecosystem}/p/{package}/v/{version}/dependencies"
supported_ecosystem = DepsDataSource.supported_ecosystem()
if purl.type in supported_ecosystem:
diff --git a/vulntotal/datasources/github.py b/vulntotal/datasources/github.py
index 3311665c4..59ac65679 100644
--- a/vulntotal/datasources/github.py
+++ b/vulntotal/datasources/github.py
@@ -68,8 +68,8 @@ def datasource_advisory_from_cve(self, cve: str) -> Iterable[VendorData]:
yield VendorData(
purl=purl,
aliases=sorted(list(set(advisory.get("identifiers", None)))),
- affected_versions=sorted(list(set(advisory.get("firstPatchedVersion", None)))),
- fixed_versions=sorted(list(set(advisory.get("vulnerableVersionRange", None)))),
+ affected_versions=sorted(list(set(advisory.get("vulnerableVersionRange", None)))),
+ fixed_versions=sorted(list(set(advisory.get("firstPatchedVersion", None)))),
)
@classmethod
@@ -101,7 +101,7 @@ def parse_advisory(interesting_edges, purl) -> Iterable[VendorData]:
"""
for edge in interesting_edges:
node = edge["node"]
- aliases = [aliase["value"] for aliase in get_item(node, "advisory", "identifiers")]
+ aliases = [alias["value"] for alias in get_item(node, "advisory", "identifiers")]
affected_versions = node["vulnerableVersionRange"].strip().replace(" ", "").split(",")
parsed_fixed_versions = get_item(node, "firstPatchedVersion", "identifier")
fixed_versions = [parsed_fixed_versions] if parsed_fixed_versions else []
diff --git a/vulntotal/datasources/gitlab.py b/vulntotal/datasources/gitlab.py
index 55aaa5b99..ae805ab00 100644
--- a/vulntotal/datasources/gitlab.py
+++ b/vulntotal/datasources/gitlab.py
@@ -31,6 +31,15 @@ class GitlabDataSource(DataSource):
license_url = "TODO"
def datasource_advisory(self, purl) -> Iterable[VendorData]:
+ """
+ Fetches advisories for a given purl from the GitLab API.
+
+ Parameters:
+ purl: A PackageURL instance representing the package to query.
+
+ Yields:
+ VendorData instance containing the advisory information for the package.
+ """
package_slug = get_package_slug(purl)
location = download_subtree(package_slug, speculative_execution=True)
if not location:
@@ -60,6 +69,15 @@ def supported_ecosystem(cls):
def get_package_slug(purl):
+ """
+ Constructs a package slug from a given purl.
+
+ Parameters:
+ purl: A PackageURL instance representing the package to query.
+
+ Returns:
+ A string representing the package slug, or None if the purl type is not supported by GitLab.
+ """
supported_ecosystem = GitlabDataSource.supported_ecosystem()
if purl.type not in supported_ecosystem:
@@ -75,6 +93,16 @@ def get_package_slug(purl):
def download_subtree(package_slug: str, speculative_execution=False):
+ """
+ Downloads and extracts a tar file from a given package slug.
+
+ Parameters:
+ package_slug: A string representing the package slug to query.
+ speculative_execution: A boolean indicating whether to log errors or not.
+
+ Returns:
+ A Path object representing the extracted location, or None if an error occurs.
+ """
url = f"https://gitlab.com/gitlab-org/security-products/gemnasium-db/-/archive/master/gemnasium-db-master.tar.gz?path={package_slug}"
response = fetch(url)
if os.path.getsize(response.location) > 0:
@@ -91,6 +119,12 @@ def download_subtree(package_slug: str, speculative_execution=False):
def clear_download(location):
+ """
+ Deletes a directory and its contents.
+
+ Parameters:
+ location: A Path object representing the directory to delete.
+ """
if location:
shutil.rmtree(location)
@@ -133,9 +167,9 @@ def get_casesensitive_slug(path, package_slug):
}
]
url = "https://gitlab.com/api/graphql"
- hasnext = True
+ has_next = True
- while hasnext:
+ while has_next:
response = requests.post(url, json=payload).json()
paginated_tree = response[0]["data"]["project"]["repository"]["paginatedTree"]
@@ -149,14 +183,26 @@ def get_casesensitive_slug(path, package_slug):
return get_gitlab_style_slug(slug_flatpath, package_slug)
payload[0]["variables"]["nextPageCursor"] = paginated_tree["pageInfo"]["endCursor"]
- hasnext = paginated_tree["pageInfo"]["hasNextPage"]
+ has_next = paginated_tree["pageInfo"]["hasNextPage"]
def parse_interesting_advisories(location, purl, delete_download=False) -> Iterable[VendorData]:
+ """
+ Parses advisories from YAML files in a given location that match a given version.
+
+ Parameters:
+ location: A Path object representing the location of the YAML files.
+ purl: PURL for the advisory.
+ version: A string representing the version to check against the affected range.
+ delete_download: A boolean indicating whether to delete the downloaded files after parsing.
+
+ Yields:
+ VendorData instance containing the advisory information for the package.
+ """
version = purl.version
path = Path(location)
- glob = "**/*.yml"
- files = (p for p in path.glob(glob) if p.is_file())
+ pattern = "**/*.yml"
+ files = [p for p in path.glob(pattern) if p.is_file()]
for file in sorted(files):
with open(file) as f:
gitlab_advisory = saneyaml.load(f)
diff --git a/vulntotal/datasources/oss_index.py b/vulntotal/datasources/oss_index.py
index d00454304..a18e65d21 100644
--- a/vulntotal/datasources/oss_index.py
+++ b/vulntotal/datasources/oss_index.py
@@ -27,6 +27,14 @@ class OSSDataSource(DataSource):
api_authenticated = "https://ossindex.sonatype.org/api/v3/authorized/component-report"
def fetch_json_response(self, coordinates):
+ """Fetch JSON response from OSS Index API for a given list of coordinates.
+
+ 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.
+ """
username = os.environ.get("OSS_USERNAME", None)
token = os.environ.get("OSS_TOKEN", None)
auth = None
@@ -35,20 +43,21 @@ def fetch_json_response(self, coordinates):
auth = (username, token)
url = self.api_authenticated
response = requests.post(url, auth=auth, json={"coordinates": coordinates})
-
- if response.status_code == 200:
+ try:
+ response.raise_for_status()
return response.json()
- elif response.status_code == 401:
- logger.error("Invalid credentials")
- elif response.status_code == 429:
- msg = (
- "Too many requests"
- if auth
- else "Too many requests: add OSS_USERNAME and OSS_TOKEN in .env file"
- )
- logger.error(msg)
- else:
- logger.error(f"unknown status code: {response.status_code} while fetching: {url}")
+ except requests.exceptions.HTTPError as e:
+ if e.response.status_code == 401:
+ logger.error("Invalid credentials")
+ elif e.response.status_code == 429:
+ msg = (
+ "Too many requests"
+ if auth
+ else "Too many requests: add OSS_USERNAME and OSS_TOKEN in .env file"
+ )
+ logger.error(msg)
+ else:
+ logger.error(f"Unknown status code: {e.response.status_code} while fetching: {url}")
def datasource_advisory(self, purl) -> Iterable[VendorData]:
if purl.type not in self.supported_ecosystem():
@@ -81,6 +90,16 @@ def supported_ecosystem(cls):
def parse_advisory(component, purl) -> Iterable[VendorData]:
+ """
+ Parse component from OSS Index API and yield VendorData.
+
+ Parameters:
+ component: A list containing a dictionary with component details.
+ purl: PURL for the advisory.
+
+ Yields:
+ VendorData instance containing advisory information for the component.
+ """
response = component[0]
vulnerabilities = response.get("vulnerabilities") or []
for vuln in vulnerabilities:
diff --git a/vulntotal/datasources/osv.py b/vulntotal/datasources/osv.py
index e7360cc24..4adf6322c 100644
--- a/vulntotal/datasources/osv.py
+++ b/vulntotal/datasources/osv.py
@@ -27,11 +27,21 @@ class OSVDataSource(DataSource):
url = "https://api.osv.dev/v1/query"
def fetch_advisory(self, payload):
- """Fetch JSON advisory from OSV API for a given package payload"""
+ """
+ Fetch JSON advisory from OSV API for a given package payload
+
+ Parameters:
+ payload: A dictionary representing the package data to query.
+
+ Returns:
+ A JSON object containing the advisory information for the package, or None if an error occurs while fetching data from the OSV API.
+ """
response = requests.post(self.url, data=str(payload))
- if not response.status_code == 200:
- logger.error(f"Error while fetching {payload}: {response.status_code}")
+ try:
+ response.raise_for_status()
+ except requests.exceptions.HTTPError as e:
+ logger.error(f"Error while fetching {payload}: {e}")
return
return response.json()
@@ -66,6 +76,12 @@ def supported_ecosystem(cls):
def parse_advisory(response, purl) -> Iterable[VendorData]:
"""
Parse response from OSV API and yield VendorData
+
+ Parameters:
+ response: A JSON object containing the response data from the OSV API.
+
+ Yields:
+ VendorData instance containing the advisory information for the package.
"""
for vuln in response.get("vulns") or []:
@@ -79,17 +95,17 @@ def parse_advisory(response, purl) -> Iterable[VendorData]:
try:
affected_versions.extend(get_item(vuln, "affected", 0, "versions") or [])
- except:
- pass
+ except (KeyError, TypeError, IndexError) as e:
+ logger.error(f"Error while parsing affected versions: {e}")
try:
- for event in get_item(vuln, "affected", 0, "ranges", 0, "events") or []:
- affected_versions.append(event.get("introduced")) if event.get(
- "introduced"
- ) else None
- fixed.append(event.get("fixed")) if event.get("fixed") else None
- except:
- pass
+ events = get_item(vuln, "affected", 0, "ranges", 0, "events") or []
+ affected_versions.extend(
+ [event.get("introduced") for event in events if event.get("introduced")]
+ )
+ fixed.extend([event.get("fixed") for event in events if event.get("fixed")])
+ except (KeyError, TypeError, IndexError) as e:
+ logger.error(f"Error while parsing events: {e}")
yield VendorData(
purl=PackageURL(purl.type, purl.namespace, purl.name),
@@ -100,7 +116,15 @@ def parse_advisory(response, purl) -> Iterable[VendorData]:
def generate_payload(purl):
- """Generate compatible payload for OSV API from a PURL"""
+ """
+ Generate compatible payload for OSV API from a PURL
+
+ Parameters:
+ purl: A PackageURL instance representing the package to query.
+
+ Returns:
+ A dictionary containing the package data compatible with the OSV API.
+ """
supported_ecosystem = OSVDataSource.supported_ecosystem()
payload = {}
diff --git a/vulntotal/datasources/snyk.py b/vulntotal/datasources/snyk.py
index 4b1a173f8..5b2418071 100644
--- a/vulntotal/datasources/snyk.py
+++ b/vulntotal/datasources/snyk.py
@@ -10,14 +10,16 @@
import logging
from typing import Iterable
from urllib.parse import quote
+from urllib.parse import unquote_plus
import requests
from bs4 import BeautifulSoup
from packageurl import PackageURL
from vulntotal.validator import DataSource
+from vulntotal.validator import InvalidCVEError
from vulntotal.validator import VendorData
-from vulntotal.vulntotal_utils import snky_constraints_satisfied
+from vulntotal.vulntotal_utils import snyk_constraints_satisfied
logger = logging.getLogger(__name__)
@@ -27,15 +29,36 @@ class SnykDataSource(DataSource):
license_url = "TODO"
def fetch(self, url):
+ """
+ Fetch the content of a given URL.
+
+ Parameters:
+ url: A string representing the URL to fetch.
+
+ Returns:
+ A string of HTML or a dictionary of JSON if the response is successful,
+ or None if the response is unsuccessful.
+ """
response = requests.get(url)
- if not response.status_code == 200:
- logger.error(f"Error while fetching {url}")
+ try:
+ response.raise_for_status()
+ except requests.exceptions.HTTPError as e:
+ logger.error(f"Error while fetching {url}: {e}")
return
if response.headers["content-type"] == "application/json, charset=utf-8":
return response.json()
return response.text
def datasource_advisory(self, purl) -> Iterable[VendorData]:
+ """
+ Fetch advisories from Snyk for a given package.
+
+ Parameters:
+ purl: A PackageURL instance representing the package.
+
+ Yields:
+ VendorData instance containing advisory information.
+ """
package_advisory_url = generate_package_advisory_url(purl)
package_advisories_list = self.fetch(package_advisory_url)
self._raw_dump.append(package_advisories_list)
@@ -49,6 +72,38 @@ def datasource_advisory(self, purl) -> Iterable[VendorData]:
if advisory_html:
yield parse_html_advisory(advisory_html, snyk_id, affected, purl)
+ def datasource_advisory_from_cve(self, cve: str) -> Iterable[VendorData]:
+ """
+ Fetch advisories from Snyk for a given CVE.
+
+ Parameters:
+ cve : CVE ID
+
+ Yields:
+ VendorData instance containing advisory information.
+ """
+ if not cve.upper().startswith("CVE-"):
+ raise InvalidCVEError
+
+ package_list = generate_payload_from_cve(cve)
+ response = self.fetch(package_list)
+ self._raw_dump = [response]
+
+ # get list of vulnerabilities for cve id
+ vulns_list = parse_cve_advisory_html(response)
+
+ # for each vulnerability get fixed version from snyk_id_url, get affected version from package_advisory_url
+ for snyk_id, package_advisory_url in vulns_list.items():
+ package_advisories_list = self.fetch(package_advisory_url)
+ package_advisories = extract_html_json_advisories(package_advisories_list)
+ affected_versions = package_advisories[snyk_id]
+ advisory_payload = generate_advisory_payload(snyk_id)
+ advisory_html = self.fetch(advisory_payload)
+ self._raw_dump.append(advisory_html)
+ purl = generate_purl(package_advisory_url)
+ if advisory_html and purl:
+ yield parse_html_advisory(advisory_html, snyk_id, affected_versions, purl)
+
@classmethod
def supported_ecosystem(cls):
return {
@@ -68,6 +123,15 @@ def supported_ecosystem(cls):
def generate_package_advisory_url(purl):
+ """
+ Generate a URL for fetching advisories from Snyk for a given package.
+
+ Parameters:
+ purl: A PackageURL instance representing the package.
+
+ Returns:
+ A string containing the URL or None if the package is not supported by Snyk.
+ """
url_package_advisories = "https://security.snyk.io/package/{ecosystem}/{package}"
# Pseudo API, unfortunately gives only 30 vulnerability per package, but this is the best we have for unmanaged packages
@@ -102,14 +166,78 @@ def generate_package_advisory_url(purl):
)
+def generate_purl(package_advisory_url):
+ """
+ Generates purl from Package advisory url.
+
+ Parameters:
+ package_advisory_url: URL of the package on Snyk.
+
+ Returns:
+ A PackageURL instance representing the package
+ """
+ package_advisory_url = unquote_plus(
+ package_advisory_url.replace("https://security.snyk.io/package/", "")
+ )
+ supported_ecosystems = {v: k for (k, v) in SnykDataSource.supported_ecosystem().items()}
+
+ package_url_split = package_advisory_url.split("/")
+ pkg_type = package_url_split[0]
+
+ pkg_name = None
+ namespace = None
+ qualifiers = {}
+
+ if pkg_type == "maven":
+ pkg_name = package_url_split[1].split(":")[1]
+ namespace = package_url_split[1].split(":")[0]
+
+ elif pkg_type == "composer":
+ pkg_name = package_url_split[-1]
+ namespace = package_url_split[-2]
+
+ elif pkg_type == "golang":
+ pkg_name = package_url_split[-1]
+ namespace = "/".join(package_url_split[1:-1])
+
+ elif pkg_type == "npm":
+ # handle scoped npm packages
+ if "@" in package_advisory_url:
+ namespace = package_url_split[-2]
+
+ pkg_name = package_url_split[-1]
+
+ elif pkg_type == "linux":
+ pkg_name = package_url_split[-1]
+ qualifiers["distro"] = package_url_split[1]
+
+ elif pkg_type in ("cocoapods", "hex", "nuget", "pip", "rubygems", "unmanaged"):
+ pkg_name = package_url_split[-1]
+
+ if pkg_type is None or pkg_name is None:
+ logger.error("Invalid package advisory url, package type or name is missing")
+ return
+
+ return PackageURL(type=supported_ecosystems[pkg_type], name=pkg_name, namespace=namespace)
+
+
def extract_html_json_advisories(package_advisories):
- vulnerablity = {}
+ """
+ Extract vulnerability information from HTML or JSON advisories.
+
+ Parameters:
+ package_advisories: A string of HTML or a dictionary of JSON containing advisories for a package.
+
+ Returns:
+ A dictionary mapping vulnerability IDs to lists of affected versions for the package.
+ """
+ vulnerability = {}
# If advisories are json and is obtained through pseudo API
if isinstance(package_advisories, dict):
if package_advisories["status"] == "ok":
for vuln in package_advisories["vulnerabilities"]:
- vulnerablity[vuln["id"]] = vuln["semver"]["vulnerable"]
+ vulnerability[vuln["id"]] = vuln["semver"]["vulnerable"]
else:
soup = BeautifulSoup(package_advisories, "html.parser")
vulns_table = soup.find("tbody", class_="vue--table__tbody")
@@ -121,11 +249,23 @@ def extract_html_json_advisories(package_advisories):
"span", class_="vue--chip vulnerable-versions__chip vue--chip--default"
)
affected_versions = [vers.text.strip() for vers in ranges]
- vulnerablity[anchor["href"].rsplit("/", 1)[-1]] = affected_versions
- return vulnerablity
+ vulnerability[anchor["href"].rsplit("/", 1)[-1]] = affected_versions
+ return vulnerability
def parse_html_advisory(advisory_html, snyk_id, affected, purl) -> VendorData:
+ """
+ Parse HTML advisory from Snyk and extract vendor data.
+
+ Parameters:
+ advisory_html: A string of HTML containing the advisory details.
+ snyk_id: A string representing the Snyk ID of the vulnerability.
+ affected: A list of strings representing the affected versions.
+ purl: PURL for the advisory.
+
+ Returns:
+ A VendorData instance containing aliases, affected versions and fixed versions for the vulnerability.
+ """
aliases = []
fixed_versions = []
@@ -153,12 +293,41 @@ def parse_html_advisory(advisory_html, snyk_id, affected, purl) -> VendorData:
)
+def parse_cve_advisory_html(cve_advisory_html):
+ """
+ Parse CVE HTML advisory from Snyk and extract list of vulnerabilities and corresponding packages for that CVE.
+
+ Parameters:
+ advisory_html: A string of HTML containing the vulnerabilities for given CVE.
+
+ Returns:
+ A dictionary with each item representing a vulnerability. Key of each item is the SNYK_ID and value is the package advisory url on snyk website
+ """
+ cve_advisory_soup = BeautifulSoup(cve_advisory_html, "html.parser")
+ vulns_table = cve_advisory_soup.find("tbody", class_="vue--table__tbody")
+ if not vulns_table:
+ return None
+ vulns_rows = vulns_table.find_all("tr", class_="vue--table__row")
+ vulns_list = {}
+
+ for row in vulns_rows:
+ anchors = row.find_all("a", {"class": "vue--anchor"})
+ if len(anchors) != 2:
+ continue
+ snyk_id = anchors[0]["href"].split("/")[1]
+ package_advisory_url = f"https://security.snyk.io{anchors[1]['href']}"
+ vulns_list[snyk_id] = package_advisory_url
+
+ return vulns_list
+
+
def is_purl_in_affected(version, affected):
- for affected_range in affected:
- if snky_constraints_satisfied(affected_range, version):
- return True
- return False
+ return any(snyk_constraints_satisfied(affected_range, version) for affected_range in affected)
def generate_advisory_payload(snyk_id):
return f"https://security.snyk.io/vuln/{snyk_id}"
+
+
+def generate_payload_from_cve(cve_id):
+ return f"https://security.snyk.io/vuln?search={cve_id}"
diff --git a/vulntotal/datasources/vulnerablecode.py b/vulntotal/datasources/vulnerablecode.py
index 7fa4c2709..d0122db83 100644
--- a/vulntotal/datasources/vulnerablecode.py
+++ b/vulntotal/datasources/vulnerablecode.py
@@ -30,22 +30,49 @@ class VulnerableCodeDataSource(DataSource):
vc_purl_search_api_path = "api/packages/bulk_search/"
def fetch_post_json(self, payload):
+ """
+ Fetches JSON data from the VulnerableCode API using a POST request with a given payload.
+
+ Parameters:
+ payload: A dictionary representing the data to send in the request body.
+
+ Returns:
+ A JSON object containing the response data, or None if an error occurs while fetching data from the VulnerableCode API.
+ """
url = urljoin(self.global_instance, self.vc_purl_search_api_path)
response = fetch_vulnerablecode_query(url=url, payload=payload)
- if not response.status_code == 200:
+ if response.status_code != 200:
logger.error(f"Error while fetching {url}")
return
return response.json()
def fetch_get_json(self, url):
+ """
+ Fetches JSON data from a given URL using the VulnerableCode API.
+
+ Parameters:
+ url: A string representing the URL to query.
+
+ Returns:
+ A JSON object containing the response data, or None if an error occurs while fetching data from the URL.
+ """
response = fetch_vulnerablecode_query(url=url, payload=None)
- if not response.status_code == 200:
+ if response.status_code != 200:
logger.error(f"Error while fetching {url}")
return
return response.json()
def datasource_advisory(self, purl) -> Iterable[VendorData]:
- if purl.type not in self.supported_ecosystem() or not purl.version:
+ """
+ Fetches advisories for a given purl from the VulnerableCode API.
+
+ Parameters:
+ purl: A PackageURL instance representing the package to query.
+
+ Yields:
+ VendorData instance containing the advisory information for the package.
+ """
+ if purl.type not in self.supported_ecosystem() or purl.version is None:
return
metadata_advisories = self.fetch_post_json({"purls": [str(purl)]})
self._raw_dump.append(metadata_advisories)
@@ -101,10 +128,10 @@ class VCIOTokenError(Exception):
def fetch_vulnerablecode_query(url: str, payload: dict):
"""
Requires VCIO API key in .env file
- For example::
-
- VCIO_TOKEN="OJ78Os2IPfM80hqVT2ek+1QnrTKvsX1HdOMABq3pmQd"
+ For example:
+ VCIO_TOKEN='OJ78Os2IPfM80hqVT2ek+1QnrTKvsX1HdOMABq3pmQd'
"""
+
load_dotenv()
vcio_token = os.environ.get("VCIO_TOKEN", None)
if not vcio_token:
diff --git a/vulntotal/tests/test_data/snyk/html/4.html b/vulntotal/tests/test_data/snyk/html/4.html
new file mode 100644
index 000000000..6ab4ccc0a
--- /dev/null
+++ b/vulntotal/tests/test_data/snyk/html/4.html
@@ -0,0 +1,190 @@
+
+
+
+ Vulnerability DB | Snyk
+
+
+