diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml
index 56ccf23b33..ae457a239d 100644
--- a/.github/workflows/build-wheel.yml
+++ b/.github/workflows/build-wheel.yml
@@ -1,10 +1,13 @@
name: Build pip wheel
+permissions: read-all
+
on:
push:
branches: [ "main" ]
workflow_dispatch:
+jobs:
build:
name: Build wheel
runs-on: ubuntu-latest
@@ -17,10 +20,10 @@ on:
matrix:
python-version:
- "3.12"
- if: github.repository == 'intel/cve-bin-tool' && github.ref == 'refs/heads/main' # run on origin repo only
+ if: github.repository == 'intel/cve-bin-tool' # run on origin repo only
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
@@ -41,11 +44,11 @@ on:
echo "tar=$(cd dist/ && echo *.tar.gz)" >> $GITHUB_OUTPUT
echo "whl=$(cd dist/ && echo *.tar.gz)" >> $GITHUB_OUTPUT
- name: Attest Build Provenance for tar
- uses: actions/attest-build-provenance@951c0c5f8e375ad4efad33405ab77f7ded2358e4 # v1.1.1
+ uses: actions/attest-build-provenance@534b352d658f90498fd148d231fdbf88f3886a3a # v1.3.1
with:
subject-path: "dist/${{ steps.filename.outputs.tar }}"
- name: Attest Build Provenance for whl
- uses: actions/attest-build-provenance@951c0c5f8e375ad4efad33405ab77f7ded2358e4 # v1.1.1
+ uses: actions/attest-build-provenance@534b352d658f90498fd148d231fdbf88f3886a3a # v1.3.1
with:
subject-path: "dist/${{ steps.filename.outputs.whl }}"
# TODO Upload to pypi on release creation
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 17227dbb36..4d3d219d68 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -42,7 +42,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
@@ -51,7 +51,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5
+ uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -76,4 +76,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5
+ uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
index 06f9515221..6145c7451c 100644
--- a/.github/workflows/coverity.yml
+++ b/.github/workflows/coverity.yml
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/cve_bin_tool_action.yml b/.github/workflows/cve_bin_tool_action.yml
index 2e7f905d09..e1b0624b94 100644
--- a/.github/workflows/cve_bin_tool_action.yml
+++ b/.github/workflows/cve_bin_tool_action.yml
@@ -6,10 +6,11 @@ on:
permissions:
contents: read
- security-events: write
jobs:
scan:
+ permissions:
+ security-events: write
runs-on: ubuntu-latest
steps:
- uses: intel/cve-bin-tool-action@main
diff --git a/.github/workflows/cve_scan.yml b/.github/workflows/cve_scan.yml
index 62ac555af3..f74b649d2d 100644
--- a/.github/workflows/cve_scan.yml
+++ b/.github/workflows/cve_scan.yml
@@ -15,7 +15,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index 583b80eaf7..cbfbe37705 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
- name: 'Checkout Repository'
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: 'Dependency Review'
- uses: actions/dependency-review-action@0c155c5e8556a497adf53f2c18edabf945ed8e70 # v4.3.2
+ uses: actions/dependency-review-action@72eb03d02c7872a771aacd928f3123ac62ad6d3a # v4.3.3
diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml
index 95f6f9950b..bccf57f7aa 100644
--- a/.github/workflows/formatting.yml
+++ b/.github/workflows/formatting.yml
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml
index 7102a7925b..62dba8b538 100644
--- a/.github/workflows/linting.yml
+++ b/.github/workflows/linting.yml
@@ -18,7 +18,7 @@ jobs:
tool: ['isort', 'black', 'pyupgrade', 'flake8', 'bandit', 'gitlint', 'mypy', 'interrogate']
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml
index 21e9887827..c3a3d63380 100644
--- a/.github/workflows/sbom.yml
+++ b/.github/workflows/sbom.yml
@@ -22,7 +22,7 @@ jobs:
python: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index ee7af4cf41..77fe17613e 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -22,7 +22,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml
index 8a035b628f..898ce1e226 100644
--- a/.github/workflows/spelling.yml
+++ b/.github/workflows/spelling.yml
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml
index ce62e492e9..604d921d10 100644
--- a/.github/workflows/testing.yml
+++ b/.github/workflows/testing.yml
@@ -1,5 +1,7 @@
name: Testing
+permissions: read-all
+
on:
push:
pull_request:
@@ -37,7 +39,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
disable-sudo: true
egress-policy: block
@@ -74,7 +76,7 @@ jobs:
timeout-minutes: 60
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: block
allowed-endpoints: >
@@ -201,7 +203,7 @@ jobs:
LONG_TESTS: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: block
allowed-endpoints: >
@@ -337,7 +339,7 @@ jobs:
test/test_cvedb.py
- name: Upload code coverage to codecov
if: env.sbom != 'true'
- uses: codecov/codecov-action@6d798873df2b1b8e5846dba6fb86631229fbcb17 # v4.4.0
+ uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
with:
files: ./coverage.xml
flags: longtests
@@ -363,7 +365,7 @@ jobs:
EXTERNAL_SYSTEM: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: block
allowed-endpoints: >
@@ -496,7 +498,7 @@ jobs:
PYTHONIOENCODING: 'utf8'
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
@@ -581,7 +583,7 @@ jobs:
- name: Test PDF generation on Windows
run: pytest test/test_output_engine.py -k test_output_pdf --cov --cov-append --cov-report=xml
- name: Upload code coverage to codecov
- uses: codecov/codecov-action@6d798873df2b1b8e5846dba6fb86631229fbcb17 # v4.4.0
+ uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
with:
files: ./coverage.xml
flags: win-longtests
diff --git a/.github/workflows/update-cache.yml b/.github/workflows/update-cache.yml
index b2e3719194..d5457ea7f7 100644
--- a/.github/workflows/update-cache.yml
+++ b/.github/workflows/update-cache.yml
@@ -22,7 +22,7 @@ jobs:
timeout-minutes: 60
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/update-js-dependencies.yml b/.github/workflows/update-js-dependencies.yml
index 6f20545948..1bf2eb8b90 100644
--- a/.github/workflows/update-js-dependencies.yml
+++ b/.github/workflows/update-js-dependencies.yml
@@ -22,7 +22,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/update-pre-commit.yml b/.github/workflows/update-pre-commit.yml
index da409e007f..69d0f20fdb 100644
--- a/.github/workflows/update-pre-commit.yml
+++ b/.github/workflows/update-pre-commit.yml
@@ -22,7 +22,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/.github/workflows/update-spdx-header.yml b/.github/workflows/update-spdx-header.yml
index a0d33ee4d4..a69c021b78 100644
--- a/.github/workflows/update-spdx-header.yml
+++ b/.github/workflows/update-spdx-header.yml
@@ -23,7 +23,7 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
+ uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
with:
egress-policy: audit
diff --git a/README.md b/README.md
index 8b94c51e3c..8038c6ad15 100644
--- a/README.md
+++ b/README.md
@@ -425,7 +425,8 @@ CVE Data Download:
-u {now,daily,never,latest}, --update {now,daily,never,latest}
update schedule for data sources and exploits database (default: daily)
--nvd-api-key NVD_API_KEY
- specify NVD API key (used to improve NVD rate limit)
+ Specify NVD API key (used to improve NVD rate limit).
+ Set to `no` to ignore any keys in the environment.
-d DISABLE_DATA_SOURCE, --disable-data-source DISABLE_DATA_SOURCE
comma-separated list of data sources (CURL, EPSS, GAD, NVD, OSV, REDHAT, RSD) to disable (default: NONE)
diff --git a/cve_bin_tool/checkers/dnsmasq.py b/cve_bin_tool/checkers/dnsmasq.py
index 1314a9e8d8..308999545a 100644
--- a/cve_bin_tool/checkers/dnsmasq.py
+++ b/cve_bin_tool/checkers/dnsmasq.py
@@ -22,7 +22,7 @@ class DnsmasqChecker(Checker):
VERSION_PATTERNS = [
r"dnsmasq-[a-z_]*([0-9]+\.[0-9]+)",
r"([0-9]+\.[0-9]+)\r?\nDnsmasq version %s",
- r"Dnsmasq version %s %s\r?\n([0-9]+\.[0-9]+)",
+ r"Dnsmasq version (?:|%s %s\r?\n)([0-9]+\.[0-9]+)",
r"([0-9]+\.[0-9]+)\r?\nstarted, version %s DNS disabled",
]
VENDOR_PRODUCT = [
diff --git a/cve_bin_tool/cli.py b/cve_bin_tool/cli.py
index d76d64ef30..ce05754e92 100644
--- a/cve_bin_tool/cli.py
+++ b/cve_bin_tool/cli.py
@@ -49,6 +49,7 @@
gad_source,
nvd_source,
osv_source,
+ purl2cpe_source,
redhat_source,
)
from cve_bin_tool.error_handler import (
@@ -151,7 +152,12 @@ def main(argv=None):
"--nvd-api-key",
action="store",
default="",
- help="specify NVD API key (used to improve NVD rate limit)",
+ help=textwrap.dedent(
+ """\
+ Specify NVD API key (used to improve NVD rate limit).
+ Set to `no` to ignore any keys in the environment.
+ """
+ ),
)
data_source_disable_help = f'comma-separated list of data sources ({", ".join(DataSourceSupport.available_data_sources())}) to disable (default: NONE)'
data_sources_group.add_argument(
@@ -722,6 +728,10 @@ def main(argv=None):
source_epss = epss_source.Epss_Source()
enabled_sources.append(source_epss)
+ if "PURL2CPE" not in disabled_sources:
+ source_purl2cpe = purl2cpe_source.PURL2CPE_Source()
+ enabled_sources.append(source_purl2cpe)
+
if "NVD" not in disabled_sources:
source_nvd = nvd_source.NVD_Source(
nvd_type=nvd_type,
diff --git a/cve_bin_tool/cvedb.py b/cve_bin_tool/cvedb.py
index 3dcc2f41a5..14a8018f6f 100644
--- a/cve_bin_tool/cvedb.py
+++ b/cve_bin_tool/cvedb.py
@@ -7,6 +7,7 @@
from __future__ import annotations
import asyncio
+import contextlib
import datetime
import json
import logging
@@ -28,6 +29,7 @@
gad_source,
nvd_source,
osv_source,
+ purl2cpe_source,
)
from cve_bin_tool.error_handler import ERROR_CODES, CVEDBError, ErrorMode, SigningError
from cve_bin_tool.fetch_json_db import Fetch_JSON_DB
@@ -58,6 +60,7 @@ class CVEDB:
epss_source.Epss_Source,
osv_source.OSV_Source,
gad_source.GAD_Source,
+ purl2cpe_source.PURL2CPE_Source,
nvd_source.NVD_Source, # last to avoid data overwrites
]
@@ -1186,3 +1189,11 @@ def fetch_from_mirror(self, mirror, pubkey, ignore_signature, log_signature_erro
else:
self.clear_cached_data()
return -1
+
+ @contextlib.contextmanager
+ def with_cursor(self):
+ cursor = self.db_open_and_get_cursor()
+ try:
+ yield cursor
+ finally:
+ self.db_close()
diff --git a/cve_bin_tool/data_sources/epss_source.py b/cve_bin_tool/data_sources/epss_source.py
index e5f33b533d..b3953b4e4a 100644
--- a/cve_bin_tool/data_sources/epss_source.py
+++ b/cve_bin_tool/data_sources/epss_source.py
@@ -67,7 +67,9 @@ async def download_epss_data(self):
# Check if the file is older than 24 hours
if time_difference > timedelta(hours=24):
try:
- async with aiohttp.ClientSession(headers=HTTP_HEADERS) as session:
+ async with aiohttp.ClientSession(
+ headers=HTTP_HEADERS, trust_env=True
+ ) as session:
async with session.get(self.DATA_SOURCE_LINK) as response:
response.raise_for_status()
self.LOGGER.info("Getting EPSS data...")
@@ -87,7 +89,9 @@ async def download_epss_data(self):
else:
try:
- async with aiohttp.ClientSession(headers=HTTP_HEADERS) as session:
+ async with aiohttp.ClientSession(
+ headers=HTTP_HEADERS, trust_env=True
+ ) as session:
async with session.get(self.DATA_SOURCE_LINK) as response:
response.raise_for_status()
self.LOGGER.info("Getting EPSS data...")
diff --git a/cve_bin_tool/data_sources/nvd_source.py b/cve_bin_tool/data_sources/nvd_source.py
index 9bb8d4fa22..73e4930a5d 100644
--- a/cve_bin_tool/data_sources/nvd_source.py
+++ b/cve_bin_tool/data_sources/nvd_source.py
@@ -88,6 +88,13 @@ def __init__(
# store the nvd api key for use later
self.nvd_api_key = nvd_api_key
+ # if nvd_api_key was set to "No" then unset it
+ # This makes it easier to disable usage from the command line
+ # and over-riding existing environment variables.
+ if self.nvd_api_key.lower() == "no":
+ self.nvd_api_key = ""
+ LOGGER.info("NVD API Key was set to 'no' and will not be used")
+
async def get_cve_data(self):
"""Retrieves the CVE data from the data source."""
await self.fetch_cves()
diff --git a/cve_bin_tool/data_sources/osv_source.py b/cve_bin_tool/data_sources/osv_source.py
index bb9bb4ac91..6cfed5ef75 100644
--- a/cve_bin_tool/data_sources/osv_source.py
+++ b/cve_bin_tool/data_sources/osv_source.py
@@ -251,15 +251,7 @@ def format_data(self, all_cve_entries):
affected_data = []
for cve_item in all_cve_entries:
- cve_in_alias = None
-
- for cve in cve_item.get("aliases", []):
- if "CVE" in cve:
- cve_in_alias = cve
- break
-
- # if CVE has alias of the form "CVE-year-xxxx" keep that as CVE ID, will help in checking for duplicates
- cve_id = cve_in_alias if cve_in_alias is not None else cve_item["id"]
+ cve_id = cve_item["id"]
severity = cve_item.get("severity", None)
vector = None
diff --git a/cve_bin_tool/data_sources/purl2cpe_source.py b/cve_bin_tool/data_sources/purl2cpe_source.py
new file mode 100644
index 0000000000..6fa17be6b5
--- /dev/null
+++ b/cve_bin_tool/data_sources/purl2cpe_source.py
@@ -0,0 +1,76 @@
+from __future__ import annotations
+
+import zipfile
+from io import BytesIO
+from pathlib import Path
+
+import aiohttp
+
+from cve_bin_tool.data_sources import DISK_LOCATION_DEFAULT, Data_Source
+from cve_bin_tool.error_handler import ErrorMode
+from cve_bin_tool.log import LOGGER
+from cve_bin_tool.version import HTTP_HEADERS
+
+
+class PURL2CPE_Source(Data_Source):
+ """Class to retrieve purl-cpe mapping database (PURL2CPE)"""
+
+ SOURCE = "PURL2CPE"
+ CACHEDIR = DISK_LOCATION_DEFAULT
+ LOGGER = LOGGER.getChild("CVEDB")
+ PURL2CPE_URL = "https://github.com/scanoss/purl2cpe/raw/main/purl2cpe.db.zip"
+
+ def __init__(
+ self, error_mode: ErrorMode = ErrorMode.TruncTrace, incremental_update=False
+ ):
+ self.cachedir = self.CACHEDIR
+ self.purl2cpe_path = str(Path(self.cachedir) / "purl2cpe")
+ self.source_name = self.SOURCE
+ self.error_mode = error_mode
+ self.incremental_update = incremental_update
+ self.purl2cpe_url = self.PURL2CPE_URL
+ self.session = None
+
+ async def fetch_cves(self):
+ """Fetches PURL2CPE database and places it in purl2cpe_path."""
+ LOGGER.info("Getting PURL2CPE data...")
+
+ if not Path(self.purl2cpe_path).exists():
+ Path(self.purl2cpe_path).mkdir()
+
+ if not self.session:
+ connector = aiohttp.TCPConnector(limit_per_host=10)
+ self.session = aiohttp.ClientSession(
+ connector=connector, headers=HTTP_HEADERS, trust_env=True
+ )
+
+ try:
+ response = await self.session.get(self.purl2cpe_url)
+ if response.status == 200:
+ data = await response.read()
+ with zipfile.ZipFile(BytesIO(data), "r") as zip_ref:
+ zip_ref.extractall(self.purl2cpe_path)
+ else:
+ LOGGER.debug(f"Failed to download file. Status code: {response.status}")
+
+ except Exception as e:
+ LOGGER.debug(f"Error fetching PURL2CPE data: {e}")
+
+ await self.session.close()
+ self.session = None
+
+ async def get_cve_data(self):
+ """Fetches PURL2CPE Database."""
+ # skip if connection fails
+ try:
+ await self.fetch_cves()
+ except Exception as e:
+ LOGGER.debug(f"Error while fetching PURL2CPE Data: {e}")
+ LOGGER.error("Unable to fetch PURL2CPE Data, skipping PURL2CPE.")
+ if self.session is not None:
+ await self.session.close()
+ return (list(), list()), self.source_name
+
+ if self.session is not None:
+ await self.session.close()
+ return (list(), list()), self.source_name
diff --git a/cve_bin_tool/egg_updater.py b/cve_bin_tool/egg_updater.py
index 3b6421a3db..70e6b6b932 100644
--- a/cve_bin_tool/egg_updater.py
+++ b/cve_bin_tool/egg_updater.py
@@ -2,11 +2,12 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import ast
+import importlib.util
import os
import sys
from io import StringIO
-from setuptools import Distribution, find_packages
+from setuptools import Distribution
try:
from cve_bin_tool.version import VERSION
@@ -59,44 +60,21 @@ def update_egg() -> None:
with StringIO() as f:
cwd = os.getcwd()
os.chdir(os.path.join(os.path.dirname(__file__), ".."))
+ setup_spec = importlib.util.spec_from_file_location(
+ "setup", os.path.join(os.path.dirname(__file__), "..", "setup.py")
+ )
+ setup_module = importlib.util.module_from_spec(setup_spec)
+ setup_spec.loader.exec_module(setup_module)
+ setup_kwargs = setup_module.setup_kwargs
sys.stdout = f
sys.stderr = f
- dist = Distribution(
+ setup_kwargs.update(
dict(
script_name="setup.py",
script_args=["egg_info"],
- name="cve-bin-tool",
- version=VERSION,
- packages=find_packages(
- exclude=["locales", "presentation"],
- ),
- entry_points={
- "console_scripts": [
- "cve-bin-tool = cve_bin_tool.cli:main",
- "csv2cve = cve_bin_tool.csv2cve:main",
- ],
- "cve_bin_tool.checker": [
- "{} = cve_bin_tool.checkers.{}:{}".format(
- filename.replace(".py", ""),
- filename.replace(".py", ""),
- "".join(
- (filename.replace(".py", "") + " checker")
- .replace("_", " ")
- .title()
- .split()
- ),
- )
- for filename in os.listdir(
- os.path.join(
- os.path.abspath(os.path.dirname(__file__)),
- "checkers",
- )
- )
- if filename.endswith(".py") and "__init__" not in filename
- ],
- },
)
)
+ dist = Distribution(setup_kwargs)
dist.parse_command_line()
dist.run_commands()
sys.stdout = sys.__stdout__
diff --git a/cve_bin_tool/input_engine.py b/cve_bin_tool/input_engine.py
index f31bacb59e..f6ab2fcac6 100644
--- a/cve_bin_tool/input_engine.py
+++ b/cve_bin_tool/input_engine.py
@@ -59,9 +59,6 @@ class InputEngine:
- validate_product(self, product: str) -> bool:
Validates if a product name conforms to the CPE 2.3 standard.
- - input_vex(self) -> None:
- Parses input data from a CycloneDX VEX file.
-
- parse_data(self, fields: Set[str], data: Iterable) -> None:
Parses common data structure for CSV and JSON input formats.
diff --git a/cve_bin_tool/output_engine/__init__.py b/cve_bin_tool/output_engine/__init__.py
index 43d5abfeaf..0298f14e81 100644
--- a/cve_bin_tool/output_engine/__init__.py
+++ b/cve_bin_tool/output_engine/__init__.py
@@ -713,6 +713,7 @@ def __init__(
self.sbom_format = sbom_format
self.sbom_root = sbom_root
self.offline = offline
+ self.sbom_packages = {}
def output_cves(self, outfile, output_type="console"):
"""Output a list of CVEs
@@ -825,6 +826,7 @@ def generate_vex(self, all_cve_data: dict[ProductInfo, CVEData], filename: str):
"NVD": "https://nvd.nist.gov/vuln/detail/",
"OSV": "https://osv.dev/list?ecosystem=&q=",
"RSD": "https://nvd.nist.gov/vuln/detail/",
+ "REDHAT": "https://access.redhat.com/security/cve/",
}
# Generate VEX file
vex_output = {"bomFormat": "CycloneDX", "specVersion": "1.4", "version": 1}
@@ -914,7 +916,6 @@ def generate_sbom(
):
"""Create SBOM package and generate SBOM file."""
# Create SBOM
- sbom_packages = {}
sbom_relationships = []
my_package = SBOMPackage()
sbom_relationship = SBOMRelationship()
@@ -933,7 +934,7 @@ def generate_sbom(
my_package.set_supplier("UNKNOWN", "NOASSERTION")
# Store package data
- sbom_packages[(my_package.get_name(), my_package.get_value("version"))] = (
+ self.sbom_packages[(my_package.get_name(), my_package.get_value("version"))] = (
my_package.get_package()
)
sbom_relationship.initialise()
@@ -945,18 +946,18 @@ def generate_sbom(
my_package.initialise()
my_package.set_name(product_data.product)
my_package.set_version(product_data.version)
- if product_data.vendor != "UNKNOWN":
+ if product_data.vendor.casefold() != "UNKNOWN".casefold():
my_package.set_supplier("Organization", product_data.vendor)
my_package.set_licensedeclared(license)
my_package.set_licenseconcluded(license)
if not (
(my_package.get_name(), my_package.get_value("version"))
- in sbom_packages
+ in self.sbom_packages
and product_data.vendor == "unknown"
):
location = product_data.location
my_package.set_evidence(location) # Set location directly
- sbom_packages[
+ self.sbom_packages[
(my_package.get_name(), my_package.get_value("version"))
] = my_package.get_package()
sbom_relationship.initialise()
@@ -967,7 +968,7 @@ def generate_sbom(
# Generate SBOM
my_sbom = SBOM()
- my_sbom.add_packages(sbom_packages)
+ my_sbom.add_packages(self.sbom_packages)
my_sbom.add_relationships(sbom_relationships)
my_generator = SBOMGenerator(
sbom_type=sbom_type,
diff --git a/cve_bin_tool/parsers/__init__.py b/cve_bin_tool/parsers/__init__.py
index c3ac1fc6ed..632dd7d6c7 100644
--- a/cve_bin_tool/parsers/__init__.py
+++ b/cve_bin_tool/parsers/__init__.py
@@ -1,11 +1,19 @@
# Copyright (C) 2022 Intel Corporation
# SPDX-License-Identifier: GPL-3.0-or-later
+from __future__ import annotations
+
+import re
+import sqlite3
+from pathlib import Path
+
from packageurl import PackageURL
+from cve_bin_tool.error_handler import CVEDBError
from cve_bin_tool.util import ProductInfo, ScanInfo
__all__ = [
+ "parse",
"Parser",
"java",
"javascript",
@@ -18,6 +26,7 @@
"php",
"perl",
"dart",
+ "env",
]
@@ -67,7 +76,7 @@ def find_vendor(self, product, version):
# To handle multiple vendors, return all combinations of product/vendor mappings
for v in vendor_package_pair:
vendor = v["vendor"]
- location = v.get("location", "/usr/local/bin/product")
+ location = v.get("location", self.filename)
self.logger.debug(f"{file_path} {product} {version} by {vendor}")
vendorlist.append(
ScanInfo(ProductInfo(vendor, product, version, location), file_path)
@@ -79,14 +88,90 @@ def find_vendor(self, product, version):
)
return vendorlist
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generate purl string based on various components."""
purl = PackageURL(
type=self.purl_pkg_type,
namespace=vendor,
name=product,
- version=version,
qualifiers=qualifier,
subpath=subpath,
)
return purl
+
+ def find_vendor_from_purl(self, purl, ver) -> tuple[list[ScanInfo], bool]:
+ """
+ Finds the vendor information for a given PackageURL (purl) and version from the database.
+
+ This method queries the database to retrieve Common Platform Enumeration (CPE) data associated with the given purl.
+ It then decodes the CPE data to extract vendor, product, and version information. If the version matches the provided
+ version, it constructs a ScanInfo object for each matching entry and returns a list of these objects.
+ """
+ try:
+ purl = purl.to_dict()
+ param1 = f"pkg:{purl['type']}/{purl['name']}"
+ param2 = f"pkg:{purl['type']}/%/{purl['name']}"
+
+ query = """
+ SELECT cpe from purl2cpe WHERE purl LIKE ?
+ UNION
+ SELECT cpe from purl2cpe WHERE purl LIKE ?
+ """
+ cursor = self.db_open_and_get_cursor()
+ cursor.execute(query, (param1, param2))
+ cpeList = cursor.fetchall()
+ vendorlist: list[ScanInfo] = []
+ vendors = set()
+
+ if cpeList != []:
+ for item in cpeList:
+ vendor, _, _ = self.decode_cpe23(str(item))
+ vendors.add((vendor, purl["name"]))
+ else:
+ return vendorlist, False
+
+ purl_with_ver = f"{str(purl)}@{ver}"
+ for vendor, product in vendors:
+ vendorlist.append(
+ ScanInfo(
+ ProductInfo(
+ vendor,
+ product,
+ ver,
+ "/usr/local/bin/product",
+ purl_with_ver,
+ ),
+ self.filename,
+ )
+ )
+
+ return vendorlist, True
+ except Exception as e:
+ self.logger.error(f"Error occurred: {e}")
+ return [], False
+
+ def db_open_and_get_cursor(self) -> sqlite3.Cursor:
+ """Opens connection to sqlite database, returns cursor object."""
+
+ dbpath = (
+ Path("~").expanduser() / ".cache" / "cve-bin-tool" / "purl2cpe/purl2cpe.db"
+ )
+ connection = sqlite3.connect(dbpath)
+
+ if connection is not None:
+ cursor = connection.cursor()
+ if cursor is None:
+ raise CVEDBError
+ return cursor
+
+ def decode_cpe23(self, cpe23) -> tuple[str, str, str]:
+ """
+ Decodes a CPE 2.3 formatted string to extract vendor, product, and version information.
+
+ """
+
+ # split on `:` only if it's not escaped
+ cpe = re.split(r"(?= 2:
product = line.split(" ")[0].split("/")[-1]
version = line.split(" ")[1][1:].split("-")[0].split("+")[0]
- vendors = self.find_vendor(product, version)
+ purl = self.generate_purl(product)
+ vendors, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendors = self.find_vendor(product, version)
if vendors is not None:
- for v in vendors:
- self.generate_purl(
- product, version, v.product_info.vendor
- )
yield from vendors
self.logger.debug(f"Done scanning file: {self.filename}")
diff --git a/cve_bin_tool/parsers/java.py b/cve_bin_tool/parsers/java.py
index 9cb22cc6e8..e1e8a5f304 100644
--- a/cve_bin_tool/parsers/java.py
+++ b/cve_bin_tool/parsers/java.py
@@ -1,3 +1,4 @@
+# NOTE: DONE
# Copyright (C) 2022 Intel Corporation
# SPDX-License-Identifier: GPL-3.0-or-later
"""Script containing all functionalities relating to parsing of Java-based files."""
@@ -13,25 +14,25 @@
class JavaParser(Parser):
"""Class to handle parsing Java-based Packages."""
+ PARSER_MATCH_FILENAMES = [
+ "pom.xml",
+ ]
+
def __init__(self, cve_db, logger, validate=True):
super().__init__(cve_db, logger)
self.validate = validate
self.purl_pkg_type = "maven"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components of a Maven package."""
- # Normalize product, version, and vendor
+ # Normalize product
product = re.sub(r"[^a-zA-Z0-9._-]", "", product).lower()
- version = re.sub(r"[^a-zA-Z0-9.+\-]", "", version)
-
- vendor = re.sub(r"[^a-zA-Z0-9._-]", "", vendor).lower() if vendor else "UNKNOWN"
- if not product or not version:
+ if not product:
return None
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -57,7 +58,7 @@ def find_vendor(self, product, version):
for pair in vendor_package_pair:
vendor = pair["vendor"]
file_path = self.filename
- location = pair.get("location", "/usr/local/bin/product")
+ location = pair.get("location", self.filename)
self.logger.debug(f"{file_path} {product} {version} by {vendor}")
info.append(
ScanInfo(ProductInfo(vendor, product, version, location), file_path)
@@ -100,7 +101,10 @@ def run_checker(self, filename):
if product is None and parent is not None:
product = parent.find(schema + "artifactId").text
if product is not None and version is not None:
- product_info = self.find_vendor(product, version)
+ purl = self.generate_purl(product)
+ product_info, result = self.find_vendor_from_purl(purl, version)
+ if not result:
+ product_info = self.find_vendor(product, version)
if product_info is not None:
yield from product_info
@@ -133,7 +137,14 @@ def run_checker(self, filename):
self.logger.debug(f"{file_path} {product.text} {version}")
if version[0].isdigit():
# Valid version identifier
- product_info = self.find_vendor(product.text, version)
+ purl = self.generate_purl(product.text)
+ product_info, result = self.find_vendor_from_purl(
+ purl, version
+ )
+ if not result:
+ product_info = self.find_vendor(
+ product.text, version
+ )
if product_info is not None:
yield from product_info
self.logger.debug(f"Done scanning file: {filename}")
diff --git a/cve_bin_tool/parsers/javascript.py b/cve_bin_tool/parsers/javascript.py
index 80a257f60c..f633654486 100644
--- a/cve_bin_tool/parsers/javascript.py
+++ b/cve_bin_tool/parsers/javascript.py
@@ -11,22 +11,23 @@
class JavascriptParser(Parser):
"""Parser for javascript's package-lock.json files"""
+ PARSER_MATCH_FILENAMES = [
+ "package-lock.json",
+ ]
+
def __init__(self, cve_db, logger):
super().__init__(cve_db, logger)
self.purl_pkg_type = "npm"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components."""
product = re.sub(r"[^a-zA-Z0-9._-]", "", product).lower()
- version = re.sub(r"[^a-zA-Z0-9.+\-]", "", version)
- vendor = "UNKNOWN" # Typically, the vendor is not explicitly defined for npm packages
- if not product or not version:
+ if not product:
return None
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -46,7 +47,11 @@ def run_checker(self, filename):
if "name" in data and "version" in data:
product = data["name"]
version = data["version"]
- vendor = self.find_vendor(product, version)
+ purl = self.generate_purl(product)
+ vendor, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendor = self.find_vendor(product, version)
else:
vendor = None
if vendor is not None:
@@ -95,7 +100,11 @@ def run_checker(self, filename):
product_version_mapping.append((product, version))
for product, version in product_version_mapping:
- vendor = self.find_vendor(product, version)
+ purl = self.generate_purl(product, "")
+ vendor, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendor = self.find_vendor(product, version)
if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
diff --git a/cve_bin_tool/parsers/parse.py b/cve_bin_tool/parsers/parse.py
index acb8fc328a..fccca7f834 100644
--- a/cve_bin_tool/parsers/parse.py
+++ b/cve_bin_tool/parsers/parse.py
@@ -1,40 +1,45 @@
# Copyright (C) 2022 Intel Corporation
# SPDX-License-Identifier: GPL-3.0-or-later
+from __future__ import annotations
-from cve_bin_tool.parsers.dart import DartParser
-from cve_bin_tool.parsers.go import GoParser
-from cve_bin_tool.parsers.java import JavaParser
-from cve_bin_tool.parsers.javascript import JavascriptParser
-from cve_bin_tool.parsers.perl import PerlParser
-from cve_bin_tool.parsers.php import PhpParser
-from cve_bin_tool.parsers.python import PythonParser, PythonRequirementsParser
-from cve_bin_tool.parsers.r import RParser
-from cve_bin_tool.parsers.ruby import RubyParser
-from cve_bin_tool.parsers.rust import RustParser
-from cve_bin_tool.parsers.swift import SwiftParser
-
-valid_files = {
- "pom.xml": JavaParser,
- "package-lock.json": JavascriptParser,
- "Cargo.lock": RustParser,
- "renv.lock": RParser,
- "requirements.txt": PythonRequirementsParser,
- "go.mod": GoParser,
- "PKG-INFO: ": PythonParser,
- "METADATA: ": PythonParser,
- "Gemfile.lock": RubyParser,
- "Package.resolved": SwiftParser,
- "composer.lock": PhpParser,
- "cpanfile": PerlParser,
- "pubspec.lock": DartParser,
-}
+import sys
+
+if sys.version_info >= (3, 10):
+ from importlib import metadata as importlib_metadata
+else:
+ import importlib_metadata
+
+from cve_bin_tool.parsers import Parser
+
+PARSERS_ENTRYPOINT = "cve_bin_tool.parsers"
+
+
+def load_valid_files() -> dict[str, list[type[Parser]]]:
+ """Loads file parsers"""
+ valid_files: dict[str, list[type[Parser]]] = {}
+ for entrypoint in importlib_metadata.entry_points().select(
+ group=PARSERS_ENTRYPOINT
+ ):
+ parser_cls = entrypoint.load()
+ for match_filename in getattr(parser_cls, "PARSER_MATCH_FILENAMES", []):
+ valid_files.setdefault(match_filename, [])
+ valid_files[match_filename].append(parser_cls)
+ for match_filename in valid_files:
+ valid_files[match_filename] = list(set(valid_files[match_filename]))
+ return valid_files
+
+
+valid_files = load_valid_files()
def parse(filename, output, cve_db, logger):
"""
Parses the given filename using the appropriate parser.
"""
+ parsers = []
for file in list(valid_files.keys()):
if file in output:
- parser = valid_files[file](cve_db, logger)
- yield from parser.run_checker(filename)
+ for valid_file_parser in valid_files[file]:
+ parsers.append(valid_file_parser(cve_db, logger))
+ for parser in parsers:
+ yield from parser.run_checker(filename)
diff --git a/cve_bin_tool/parsers/perl.py b/cve_bin_tool/parsers/perl.py
index c70ad03d61..5bff60f023 100644
--- a/cve_bin_tool/parsers/perl.py
+++ b/cve_bin_tool/parsers/perl.py
@@ -9,23 +9,24 @@
class PerlParser(Parser):
"""Parser for perl's cpan files"""
+ PARSER_MATCH_FILENAMES = [
+ "cpanfile",
+ ]
+
def __init__(self, cve_db, logger):
super().__init__(cve_db, logger)
self.purl_pkg_type = "cpan"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components."""
- # Normalize product, version, and vendor for Perl packages
+ # Normalize product and vendor for Perl packages
product = re.sub(r"[^a-zA-Z0-9._-]", "", product).lower()
- version = re.sub(r"[^a-zA-Z0-9.+-]", "", version)
- vendor = "UNKNOWN" # Typically, the vendor is not explicitly defined for CPAN packages
- if not product or not version:
+ if not product:
return None
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -55,7 +56,13 @@ def run_checker(self, filename):
# Print the extracted dependencies
for dependency in dependencies:
- vendor = self.find_vendor(dependency[0], dependency[1])
+ product = dependency[0]
+ version = dependency[1]
+ purl = self.generate_purl(product)
+ vendor, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendor = self.find_vendor(product, version)
if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
diff --git a/cve_bin_tool/parsers/php.py b/cve_bin_tool/parsers/php.py
index 4174d9971e..0fca9bfae3 100644
--- a/cve_bin_tool/parsers/php.py
+++ b/cve_bin_tool/parsers/php.py
@@ -1,3 +1,6 @@
+# NOTE: remains not complete
+
+
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: GPL-3.0-or-later
"""Python script containing all functionalities related to parsing of php's composer.lock files."""
@@ -14,23 +17,24 @@ class PhpParser(Parser):
generate PURLs (Package URLs) for the listed packages.
"""
+ PARSER_MATCH_FILENAMES = [
+ "composer.lock",
+ ]
+
def __init__(self, cve_db, logger):
"""Initialize the PhpParser."""
super().__init__(cve_db, logger)
self.purl_pkg_type = "composer"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components."""
- vendor = re.sub(r"[^a-zA-Z0-9._-]", "", vendor).lower()
product = re.sub(r"[^a-zA-Z0-9._-]", "", product).lower()
- version = re.sub(r"[^a-zA-Z0-9.+-]", "", version)
- if not vendor or not product or not version:
+ if not product:
return None
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -53,7 +57,11 @@ def run_checker(self, filename):
version = version[1:]
if "dev" in version:
continue
- vendor = self.find_vendor(product, version)
+ purl = self.generate_purl(product)
+ vendor, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendor = self.find_vendor(product, version)
if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
diff --git a/cve_bin_tool/parsers/python.py b/cve_bin_tool/parsers/python.py
index ff8f12fe78..6d1201993f 100644
--- a/cve_bin_tool/parsers/python.py
+++ b/cve_bin_tool/parsers/python.py
@@ -20,23 +20,24 @@ class PythonRequirementsParser(Parser):
requirements.txt) and generate PURLs (Package URLs) for the listed packages.
"""
+ PARSER_MATCH_FILENAMES = [
+ "requirements.txt",
+ ]
+
def __init__(self, cve_db, logger):
"""Initialize the python requirements file parser."""
- self.purl_pkg_type = "pypi"
super().__init__(cve_db, logger)
+ self.purl_pkg_type = "pypi"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components."""
product = re.sub(r"[^a-zA-Z0-9._-]", "", product).lower()
- version = re.sub(r"[^a-zA-Z0-9.+-]", "", version)
- vendor = "UNKNOWN"
- if not product or not version:
+ if not product:
return None
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -99,7 +100,12 @@ def run_checker(self, filename):
for line in lines["install"]:
product = line["metadata"]["name"]
version = line["metadata"]["version"]
- vendor = self.find_vendor(product, version)
+ purl = self.generate_purl(product)
+ vendor, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendor = self.find_vendor(product, version)
+
if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
@@ -112,23 +118,25 @@ class PythonParser(Parser):
PKG-INFO or METADATA) and generate PURLs (Package URLs) for the package.
"""
+ PARSER_MATCH_FILENAMES = [
+ "PKG-INFO: ",
+ "METADATA: ",
+ ]
+
def __init__(self, cve_db, logger):
"""Initialize the python package metadata parser."""
- self.purl_pkg_type = "pypi"
super().__init__(cve_db, logger)
+ self.purl_pkg_type = "pypi"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components."""
product = re.sub(r"[^a-zA-Z0-9._-]", "", product).lower()
- version = re.sub(r"[^a-zA-Z0-9.+-]", "", version)
- vendor = "UNKNOWN"
- if not product or not version:
+ if not product:
return None
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -148,16 +156,25 @@ def run_checker(self, filename):
try:
product = search(compile(r"^Name: (.+)$", MULTILINE), lines).group(1)
version = search(compile(r"^Version: (.+)$", MULTILINE), lines).group(1)
- vendor_package_pair = self.cve_db.get_vendor_product_pairs(product)
- if vendor_package_pair != []:
- for pair in vendor_package_pair:
- vendor = pair["vendor"]
- location = pair.get("location", "/usr/local/bin/product")
- file_path = self.filename
- self.logger.debug(f"{file_path} is {vendor}.{product} {version}")
- yield ScanInfo(
- ProductInfo(vendor, product, version, location), file_path
- )
+ purl = self.generate_purl(product)
+ vendor, result = self.find_vendor_from_purl(purl, version)
+
+ if vendor is not None:
+ yield from vendor
+
+ if not result:
+ vendor_package_pair = self.cve_db.get_vendor_product_pairs(product)
+ if vendor_package_pair != []:
+ for pair in vendor_package_pair:
+ vendor = pair["vendor"]
+ location = pair.get("location", self.filename)
+ file_path = self.filename
+ self.logger.debug(
+ f"{file_path} is {vendor}.{product} {version}"
+ )
+ yield ScanInfo(
+ ProductInfo(vendor, product, version, location), file_path
+ )
# There are packages with a METADATA file in them containing different data from what the tool expects
except AttributeError:
diff --git a/cve_bin_tool/parsers/r.py b/cve_bin_tool/parsers/r.py
index 32973a0889..a907b28fa1 100644
--- a/cve_bin_tool/parsers/r.py
+++ b/cve_bin_tool/parsers/r.py
@@ -26,25 +26,24 @@ class RParser(Parser):
"""
+ PARSER_MATCH_FILENAMES = [
+ "renv.lock",
+ ]
+
def __init__(self, cve_db, logger):
super().__init__(cve_db, logger)
self.purl_pkg_type = "cran"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components."""
product = re.sub(r"[^a-zA-Z0-9.-]", "", product)
- version = re.sub(r"^[^a-zA-Z0-9]|[^a-zA-Z0-9.-]", "", version)
- vendor = "UNKNOWN"
if not re.match(r"^[a-zA-Z0-9_-]", product):
return
- if version == "":
- version = "UNKNOWN"
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -61,7 +60,12 @@ def run_checker(self, filename):
for package in content["Packages"]:
product = content["Packages"][package]["Package"]
version = content["Packages"][package]["Version"]
- vendor = self.find_vendor(product, version)
+ purl = self.generate_purl(product)
+ vendor, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendor = self.find_vendor(product, version)
+
if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
diff --git a/cve_bin_tool/parsers/ruby.py b/cve_bin_tool/parsers/ruby.py
index 53d9f03709..0bc65db22c 100644
--- a/cve_bin_tool/parsers/ruby.py
+++ b/cve_bin_tool/parsers/ruby.py
@@ -1,4 +1,6 @@
-# Copyright (C) 2022 Intel Corporation
+# Copyright (C) 2024 Intel Corporation
+
+
# SPDX-License-Identifier: GPL-3.0-or-later
import re
@@ -25,27 +27,24 @@ class RubyParser(Parser):
"""
+ PARSER_MATCH_FILENAMES = [
+ "Gemfile.lock",
+ ]
+
def __init__(self, cve_db, logger):
super().__init__(cve_db, logger)
self.purl_pkg_type = "gem"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components."""
product = re.sub(r"^[^a-z]|[^a-z0-9_-]", "", product)
- version = re.sub(r"^[^0-9]|[^a-zA-Z0-9.+-]", "", version)
- vendor = re.sub(r"^[^a-z]|[^a-z0-9_-]", "", vendor)
if not re.match(r"^[a-z]|[a-z0-9_-]", product):
return
- if vendor == "":
- vendor = "UNKNOWN"
- if version == "":
- version = "UNKNOWN"
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -73,7 +72,11 @@ def run_checker(self, filename):
):
product = line.strip().split()[0]
version = line.strip().split("(")[1][:-1]
- vendors = self.find_vendor(product, version)
+ purl = self.generate_purl(product)
+ vendors, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendors = self.find_vendor(product, version)
if vendors is not None:
yield from vendors
self.logger.debug(f"Done scanning file: {self.filename}")
diff --git a/cve_bin_tool/parsers/rust.py b/cve_bin_tool/parsers/rust.py
index db292705fb..6f574f41f0 100644
--- a/cve_bin_tool/parsers/rust.py
+++ b/cve_bin_tool/parsers/rust.py
@@ -24,27 +24,24 @@ class RustParser(Parser):
Parse the Rust dependency file and yield valid PURLs for the packages listed in the file.
"""
+ PARSER_MATCH_FILENAMES = [
+ "Cargo.lock",
+ ]
+
def __init__(self, cve_db, logger):
super().__init__(cve_db, logger)
self.purl_pkg_type = "cargo"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components."""
product = re.sub(r"^[^a-zA-Z_]|[^a-zA-Z0-9_-]", "", product)
- vendor = re.sub(r"^[^a-zA-Z_]|[^a-zA-Z0-9_-]", "", vendor)
- version = re.sub(r"^[^0-9]|[^a-zA-Z0-9.+-]", "", version)
if not re.match(r"^[a-zA-Z_]|[a-zA-Z0-9_-]", product):
return
- if vendor == "":
- vendor = "UNKNOWN"
- if version == "":
- version = "UNKNOWN"
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -67,7 +64,13 @@ def run_checker(self, filename):
else:
if product == "" and version == "":
continue
- vendors = self.find_vendor(product, version)
+
+ purl = self.generate_purl(product)
+ vendors, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendors = self.find_vendor(product, version)
+
if vendors is not None:
yield from vendors
product = ""
diff --git a/cve_bin_tool/parsers/swift.py b/cve_bin_tool/parsers/swift.py
index e47b56ad96..64ba63ff9d 100644
--- a/cve_bin_tool/parsers/swift.py
+++ b/cve_bin_tool/parsers/swift.py
@@ -28,26 +28,24 @@ class SwiftParser(Parser):
"""
+ PARSER_MATCH_FILENAMES = [
+ "Package.resolved",
+ ]
+
def __init__(self, cve_db, logger):
super().__init__(cve_db, logger)
self.purl_pkg_type = "swift"
- def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
+ def generate_purl(self, product, vendor="", qualifier={}, subpath=None):
"""Generates PURL after normalizing all components."""
product = re.sub(r"[^a-zA-Z0-9_-]", "", product)
- version = re.sub(r"[^a-zA-Z0-9.+-]", "", version)
if not re.match(r"[a-zA-Z0-9_-]", product):
return
- if not vendor:
- vendor = "UNKNOWN"
- if not version:
- version = "UNKNOWN"
purl = super().generate_purl(
product,
- version,
vendor,
qualifier,
subpath,
@@ -75,7 +73,11 @@ def run_checker(self, filename):
domain = parse.netloc
self.logger.debug(domain)
- vendors = self.find_vendor(product, version)
+ purl = self.generate_purl(product)
+ vendors, result = self.find_vendor_from_purl(purl, version)
+
+ if not result:
+ vendors = self.find_vendor(product, version)
if vendors is not None:
yield from vendors
self.logger.debug(f"Done scanning file: {self.filename}")
diff --git a/cve_bin_tool/sbom_manager/__init__.py b/cve_bin_tool/sbom_manager/__init__.py
index f2249c9460..9d92107873 100644
--- a/cve_bin_tool/sbom_manager/__init__.py
+++ b/cve_bin_tool/sbom_manager/__init__.py
@@ -29,7 +29,7 @@
class SBOMManager:
"""
- Class: InputEngine
+ Class: SBOMManager
This class is responsible for parsing various SBOM file formats (SPDX, CycloneDX, SWID) in the CVE Bin Tool.
diff --git a/cve_bin_tool/util.py b/cve_bin_tool/util.py
index 6c9d5b247c..2564464cdf 100644
--- a/cve_bin_tool/util.py
+++ b/cve_bin_tool/util.py
@@ -13,6 +13,7 @@
from typing import DefaultDict, Iterator, List, NamedTuple, Pattern, Set, Union
import requests
+from packageurl import PackageURL
from cve_bin_tool.log import LOGGER
@@ -155,12 +156,14 @@ class ProductInfo(NamedTuple):
product: str
version: str
location: str
+ purl: Optional[str]
"""
vendor: str
product: str
version: str
location: str
+ purl: str | None = None
class ScanInfo(NamedTuple):
@@ -332,6 +335,118 @@ def validate_location(location: str) -> bool:
return bool(re.match(pattern, location))
+def decode_purl(purl: str) -> ProductInfo | None:
+ """
+ Decode a Package URL (purl) in the format: pkg:type/namespace/product@version.
+
+ Args:
+ - purl (str): Package URL (purl) string.
+
+ Returns:
+ - ProductInfo | None: An instance of ProductInfo containing the vendor, product,
+ version, location, and purl, or None if the purl is invalid.
+ """
+ location = "location/to/product"
+
+ try:
+ purl_obj = PackageURL.from_string(purl)
+ vendor = purl_obj.namespace
+ product = purl_obj.name
+ version = purl_obj.version
+ if vendor and product and version:
+ product_info = ProductInfo(
+ vendor=vendor,
+ product=product,
+ version=version,
+ location=location,
+ purl=purl,
+ )
+ return product_info
+ else:
+ raise ValueError(
+ f"Invalid purl: expected format pkg:type/namespace/product@version, got {purl}"
+ )
+
+ except Exception as e:
+ LOGGER.error(f"Error decoding purl: {e}")
+ return None
+
+
+def decode_bom_ref(ref: str) -> ProductInfo | None:
+ """
+ Decodes the BOM reference for each component.
+
+ Args:
+ - ref (str): BOM reference string
+
+ Returns:
+ - ProductInfo | None: ProductInfo object containing the vendor, product, and version,
+ or None if the reference cannot be decoded.
+
+ """
+ # urn:cbt:{bom_version}/{vendor}#{product}-{version}
+ urn_cbt_ref = re.compile(
+ r"urn:cbt:(?P.*?)\/(?P.*?)#(?P.*?)-(?P.*)"
+ )
+
+ # This URN was added to support CPE's that have dashes in their version field.
+ # urn:cbt:{bom_version}/{vendor}#{product}:{version}
+ urn_cbt_ext_ref = re.compile(
+ r"urn:cbt:(?P.*?)\/(?P.*?)#(?P.*?):(?P.*)"
+ )
+
+ # urn:cdx:serialNumber/version#bom-ref (https://cyclonedx.org/capabilities/bomlink/)
+ urn_cdx = re.compile(
+ r"urn:cdx:(?P.*?)\/(?P.*?)#(?P.*)"
+ )
+ location = "location/to/product"
+ match = urn_cbt_ext_ref.match(ref) or urn_cbt_ref.match(ref) or urn_cdx.match(ref)
+ if match:
+ urn_dict = match.groupdict()
+ if "bom_ref" in urn_dict: # For urn_cdx match
+ cdx_bom_ref = urn_dict["bom_ref"]
+ try:
+ product, version = cdx_bom_ref.rsplit("-", 1)
+ except ValueError:
+ product, version = None, None
+ vendor = None
+ else: # For urn_cbt_ext_ref or urn_cbt_ref match
+ vendor = urn_dict.get("vendor")
+ product = urn_dict.get("product")
+ version = urn_dict.get("version")
+ else:
+ return None
+
+ if product and vendor and version:
+ if validate_product_vendor(product, vendor) and validate_version(version):
+ return ProductInfo(
+ vendor.strip(), product.strip(), version.strip(), location
+ )
+
+ return None
+
+
+def validate_product_vendor(product: str, vendor: str) -> bool:
+ """
+ Validates if a product name and vendor conform to the CPE 2.3 standard.
+ Ensure product name and vendor conform to CPE 2.3 standard.
+ See https://csrc.nist.gov/schema/cpe/2.3/cpe-naming_2.3.xsd for naming specification
+ """
+ cpe_regex = r"\A([A-Za-z0-9\._\-~ %])+\Z"
+ return (
+ re.search(cpe_regex, product) is not None
+ and re.search(cpe_regex, vendor) is not None
+ )
+
+
+def validate_version(version: str) -> bool:
+ """
+ Validates if a version conform to the CPE 2.3 standard.
+ """
+ cpe_regex = r"^[a-zA-Z0-9._\-+]+$"
+ return re.search(cpe_regex, version) is not None
+
+
class DirWalk:
"""
for filename in DirWalk('*.c').walk(roots):
diff --git a/cve_bin_tool/version_scanner.py b/cve_bin_tool/version_scanner.py
index 29b27d56e8..68f71bf4a0 100644
--- a/cve_bin_tool/version_scanner.py
+++ b/cve_bin_tool/version_scanner.py
@@ -2,10 +2,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
+import itertools
import subprocess
import sys
from logging import Logger
-from pathlib import Path, PurePath
+from pathlib import Path
from typing import Iterator
from cve_bin_tool.checkers import Checker
@@ -30,10 +31,6 @@
from importlib import metadata as importlib_metadata
else:
import importlib_metadata
-if sys.version_info >= (3, 9):
- import importlib.resources as resources
-else:
- import importlib_resources as resources
class InvalidFileError(Exception):
@@ -129,16 +126,7 @@ def number_of_checkers(self) -> int:
@classmethod
def available_language_checkers(cls) -> list[str]:
"""Find Language checkers"""
- language_directory = resources.files(cls.LANGUAGE_CHECKER_ENTRYPOINT)
- parsers = language_directory.iterdir()
- language_checkers = []
- for parser in parsers:
- if str(parser).endswith(".py"):
- language = PurePath(parser).name.replace(".py", "").capitalize()
- if language not in ["__init__", "Parse"]:
- language_checkers.append(language)
-
- return sorted(language_checkers)
+ return list(sorted(map(str, set(itertools.chain(*valid_files.values())))))
def print_language_checkers(self) -> None:
"""Logs the message that lists the names of the language checkers"""
@@ -175,6 +163,7 @@ def is_executable(self, filename: str) -> tuple[bool, str | None]:
"PE32 executable",
"PE32+ executable",
"Mach-O",
+ "YAFFS",
": data",
*list(valid_files.keys()),
)
diff --git a/cve_bin_tool/vex_manager/__init__.py b/cve_bin_tool/vex_manager/__init__.py
new file mode 100644
index 0000000000..6dc51c1f57
--- /dev/null
+++ b/cve_bin_tool/vex_manager/__init__.py
@@ -0,0 +1,2 @@
+# Copyright (C) 2024 Intel Corporation
+# SPDX-License-Identifier: GPL-3.0-or-later
diff --git a/cve_bin_tool/vex_manager/generate.py b/cve_bin_tool/vex_manager/generate.py
new file mode 100644
index 0000000000..a899ceffc6
--- /dev/null
+++ b/cve_bin_tool/vex_manager/generate.py
@@ -0,0 +1,157 @@
+# Copyright (C) 2024 Intel Corporation
+# SPDX-License-Identifier: GPL-3.0-or-later
+import os
+from datetime import datetime
+from logging import Logger
+from pathlib import Path
+from typing import Dict, List, Optional
+
+from lib4sbom.data.vulnerability import Vulnerability
+from lib4vex.generator import VEXGenerator
+
+from cve_bin_tool.log import LOGGER
+from cve_bin_tool.util import CVEData, ProductInfo, Remarks
+
+
+class VEXGenerate:
+ analysis_state = {
+ "cyclonedx": {
+ Remarks.NewFound: "in_triage",
+ Remarks.Unexplored: "in_triage",
+ Remarks.Confirmed: "exploitable",
+ Remarks.Mitigated: "resolved",
+ Remarks.FalsePositive: "false_positive",
+ Remarks.NotAffected: "not_affected",
+ },
+ "csaf": {
+ Remarks.NewFound: "under_investigation",
+ Remarks.Unexplored: "under_investigation",
+ Remarks.Confirmed: "known_affected",
+ Remarks.Mitigated: "fixed",
+ Remarks.FalsePositive: "known_not_affected",
+ Remarks.NotAffected: "known_not_affected",
+ },
+ "openvex": {
+ Remarks.NewFound: "under_investigation",
+ Remarks.Unexplored: "under_investigation",
+ Remarks.Confirmed: "affected",
+ Remarks.Mitigated: "fixed",
+ Remarks.FalsePositive: "not_affected",
+ Remarks.NotAffected: "not_affected",
+ },
+ }
+
+ def __init__(
+ self,
+ product: str,
+ release: str,
+ vendor: str,
+ filename: str,
+ vextype: str,
+ all_cve_data: Dict[ProductInfo, CVEData],
+ sbom: Optional[str] = None,
+ logger: Optional[Logger] = None,
+ validate: bool = True,
+ ):
+ self.product = product
+ self.release = release
+ self.vendor = vendor
+ self.sbom = sbom
+ self.filename = filename
+ self.vextype = vextype
+ self.logger = logger or LOGGER.getChild(self.__class__.__name__)
+ self.validate = validate
+ self.all_cve_data = all_cve_data
+
+ def generate_vex(self) -> None:
+ """
+ Generates VEX code based on the specified VEX type.
+
+ Returns:
+ None
+ """
+ vexgen = VEXGenerator(vex_type=self.vextype)
+ kwargs = {"name": self.product, "release": self.release}
+ if self.sbom:
+ kwargs["sbom"] = self.sbom
+ vexgen.set_product(**kwargs)
+ if Path(self.filename).is_file():
+ self.logger.warning(
+ f"Failed to write '{self.filename}'. File already exists"
+ )
+ self.logger.info("Generating a new filename with Default Naming Convention")
+ self.filename = self.generate_vex_filename()
+ vexgen.generate(
+ project_name=self.product,
+ vex_data=self.get_vulnerabilities(),
+ metadata=self.get_metadata(),
+ filename=self.filename,
+ )
+
+ def generate_vex_filename(self) -> str:
+ """
+ Generates a VEX filename based on the current date and time.
+
+ Returns:
+ str: The generated VEX filename.
+ """
+ now = datetime.now().strftime("%Y-%m-%d.%H-%M-%S")
+ filename = os.path.abspath(
+ os.path.join(
+ os.getcwd(), f"{self.product}_{self.release}_{self.vextype}.{now}.json"
+ )
+ )
+ return filename
+
+ def get_metadata(self) -> Dict:
+ metadata = {
+ "id": f"{self.product.upper()}-{self.release}-VEX",
+ "supplier": self.vendor,
+ }
+ # other metadata can be added here
+ return metadata
+
+ def get_vulnerabilities(self) -> List[Vulnerability]:
+ """
+ Retrieves a list of vulnerabilities.
+
+ Returns:
+ A list of Vulnerability objects representing the vulnerabilities.
+ """
+ vulnerabilities = []
+ for product_info, cve_data in self.all_cve_data.items():
+ vendor, product, version, _, purl = product_info
+ for cve in cve_data["cves"]:
+ if isinstance(cve, str):
+ continue
+ vulnerability = Vulnerability(validation=self.vextype)
+ vulnerability.initialise()
+ vulnerability.set_name(product)
+ vulnerability.set_release(version)
+ vulnerability.set_id(cve.cve_number)
+ vulnerability.set_description(cve.description)
+ vulnerability.set_comment(cve.comments)
+ vulnerability.set_status(self.analysis_state[self.vextype][cve.remarks])
+ if cve.justification:
+ vulnerability.set_justification(cve.justification)
+ # vulnerability.set_remediation(cve.response)
+ detail = (
+ f"{cve.remarks.name}: {cve.comments}"
+ if cve.comments
+ else cve.remarks.name
+ )
+ # more details will be added using set_value()
+ bom_version = 1
+ ref = f"urn:cbt:{bom_version}/{vendor}#{product}:{version}"
+ if purl is None:
+ purl = f"pkg:generic/{vendor}/{product}@{version}"
+
+ vulnerability.set_value("purl", purl)
+ vulnerability.set_value("bom_link", ref)
+ vulnerability.set_value("action", detail)
+ vulnerability.set_value("source", cve.data_source)
+ vulnerability.set_value("updated", cve.last_modified)
+ # vulnerability.show_vulnerability()
+ vulnerabilities.append(vulnerability.get_vulnerability())
+ self.logger.debug(f"Vulnerabilities: {vulnerabilities}")
+ return vulnerabilities
diff --git a/cve_bin_tool/vex_manager/parse.py b/cve_bin_tool/vex_manager/parse.py
new file mode 100644
index 0000000000..0d82a000b6
--- /dev/null
+++ b/cve_bin_tool/vex_manager/parse.py
@@ -0,0 +1,115 @@
+# Copyright (C) 2024 Intel Corporation
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from typing import Any, DefaultDict, Dict, Set, Union
+
+from lib4vex.parser import VEXParser
+
+from cve_bin_tool.log import LOGGER
+from cve_bin_tool.util import ProductInfo, Remarks, decode_bom_ref, decode_purl
+
+TriageData = Dict[str, Union[Dict[str, Any], Set[str]]]
+
+
+class VEXParse:
+ """
+ A class for parsing VEX files and extracting necessary fields from the vulnerabilities.
+
+ Attributes:
+ - filename (str): The path to the VEX file.
+ - vextype (str): The type of VEX file.
+ - logger: The logger object for logging messages.
+ - parsed_data: A dictionary to store the parsed data.
+
+ Methods:
+ - __init__(self, filename: str, vextype: str, logger=None): Initializes the VEXParse object.
+ - parse_vex(self) -> DefaultDict[ProductInfo, TriageData]: Parses the VEX file and extracts the necessary fields from the vulnerabilities.
+ - process_metadata(self) -> None: Processes the metadata.
+ - process_product(self) -> None: Processes the product information.
+ - process_vulnerabilities(self, vulnerabilities) -> None: Processes the vulnerabilities and extracts the necessary fields.
+ """
+
+ analysis_state = {
+ "cyclonedx": {
+ "in_triage": Remarks.NewFound,
+ "exploitable": Remarks.Confirmed,
+ "resolved": Remarks.Mitigated,
+ "false_positive": Remarks.FalsePositive,
+ "not_affected": Remarks.NotAffected,
+ },
+ "csaf": {
+ "first_affected": Remarks.NewFound,
+ "first_fixed": Remarks.Mitigated,
+ "fixed": Remarks.Mitigated,
+ "known_affected": Remarks.Confirmed,
+ "known_not_affected": Remarks.NotAffected,
+ "last_affected": Remarks.Confirmed,
+ "recommended": Remarks.Mitigated,
+ "under_investigation": Remarks.NewFound,
+ },
+ "openvex": {
+ "not_affected": Remarks.NotAffected,
+ "affected": Remarks.Confirmed,
+ "fixed": Remarks.Mitigated,
+ "under_investigation": Remarks.NewFound,
+ },
+ }
+
+ def __init__(self, filename: str, vextype: str, logger=None):
+ self.filename = filename
+ self.vextype = vextype
+ self.logger = logger or LOGGER.getChild(self.__class__.__name__)
+ self.parsed_data = {}
+
+ def parse_vex(self) -> DefaultDict[ProductInfo, TriageData]:
+ """Parses the VEX file and extracts the necessary fields from the vulnerabilities."""
+ vexparse = VEXParser(vex_type=self.vextype)
+ vexparse.parse(self.filename)
+ self.logger.debug(f"VEX Vulnerabilities: {vexparse.get_vulnerabilities()}")
+ self.process_vulnerabilities(vexparse.get_vulnerabilities())
+ self.process_metadata(vexparse.get_metadata())
+ self.process_product(vexparse.get_product())
+ return self.parsed_data
+
+ def process_metadata(self, metadata) -> None:
+ self.parsed_metadata = metadata
+
+ def process_product(self, product) -> None:
+ self.parsed_product = product
+
+ def process_vulnerabilities(self, vulnerabilities) -> None:
+ """ "processes the vulnerabilities and extracts the necessary fields from the vulnerability."""
+ # for now cyclonedx is supported with minor tweaks other will be supported later
+ for vuln in vulnerabilities:
+ # Extract necessary fields from the vulnerability
+ cve_id = vuln.get("id")
+ remarks = self.analysis_state[self.vextype][vuln.get("status")]
+ justification = vuln.get("justification")
+ response = vuln.get("remediation")
+ comments = vuln.get("comments")
+ severity = vuln.get("severity") # Severity is not available in Lib4VEX
+ # Decode the bom reference for cyclonedx something similar would be done for other formats
+ product_info = None
+ if self.vextype == "cyclonedx":
+ product_info = decode_bom_ref(vuln.get("bom_link"))
+ elif self.vextype in ["openvex", "csaf"]:
+ product_info = decode_purl(vuln.get("purl"))
+ if product_info:
+ cve_data = {
+ "remarks": remarks,
+ "comments": comments if comments else "",
+ "response": response if response else [],
+ }
+ if justification:
+ cve_data["justification"] = justification.strip()
+
+ if severity:
+ cve_data["severity"] = severity.strip()
+
+ if product_info not in self.parsed_data:
+ self.parsed_data[product_info] = {}
+ self.parsed_data[product_info][cve_id.strip()] = cve_data
+
+ if "paths" not in self.parsed_data[product_info]:
+ self.parsed_data[product_info]["paths"] = {}
+ self.logger.debug(f"Parsed Vex Data: {self.parsed_data}")
diff --git a/doc/MANUAL.md b/doc/MANUAL.md
index 559c1fa6a6..b6a30029c6 100644
--- a/doc/MANUAL.md
+++ b/doc/MANUAL.md
@@ -125,7 +125,8 @@ which is useful if you're trying the latest code from
-u {now,daily,never,latest}, --update {now,daily,never,latest}
update schedule for data sources and exploits database (default: daily)
--nvd-api-key NVD_API_KEY
- specify NVD API key (used to improve NVD rate limit)
+ Specify NVD API key (used to improve NVD rate limit).
+ Set to `no` to ignore any keys in the environment.
-d {NVD,OSV,GAD,REDHAT,CURL} [{NVD,OSV,GAD,REDHAT,CURL} ...], --disable-data-source {NVD,OSV,GAD,REDHAT,CURL} [{NVD,OSV,GAD,REDHAT,CURL} ...]
specify data sources that should be disabled
@@ -451,6 +452,8 @@ By stating it in command line interface(cli)
cve-bin-tool --nvd-api-key your_api_key_here
```
+You can also set your API Key to be "no" on the command line, which will allow you to ignore any keys set in the environment. This is occasionally useful for testing purposes or to force cve-bin-tool to use the mirrors only.
+
Once you have set up your NVD API Key, cve-bin-tool will use it to retrieve vulnerability data from the NVD. This will ensure that you have access to the full database and will reduce the likelihood of encountering errors due to limited access.
If for any reason, the NVD API Key is not working, cve-bin-tool will automatically switch to the JSON fallback. However, it is highly recommended that you verify that your API Key is working properly to ensure access with the NVD database. To use the json method, use the flag [`-n json-nvd` or `--nvd json-nvd`](https://github.com/intel/cve-bin-tool/blob/main/doc/MANUAL.md#-n-jsonapi---nvd-jsonapi) . You can use it in the following way
diff --git a/doc/PARSERS.rst b/doc/PARSERS.rst
new file mode 100644
index 0000000000..8857c0e770
--- /dev/null
+++ b/doc/PARSERS.rst
@@ -0,0 +1,261 @@
+Adding a new parser to cve-bin-tool
+===================================
+
+Overview
+--------
+
+Parsers enhance ``cve-bin-tool`` by helping it discover vulnerabilities for
+different file types and manifest formats.
+
+Parsers
+-------
+
+The following parsers have been added to the project:
+
+- **DartParser**
+- **GoParser**
+- **JavaParser**
+- **JavascriptParser**
+- **PerlParser**
+- **PhpParser**
+- **PythonParser**
+- **PythonRequirementsParser**
+- **RParser**
+- **RubyParser**
+- **RustParser**
+- **SwiftParser**
+- **BanditParser**
+
+Usage
+-----
+
+To utilize these parsers, ensure that your project includes the following imports:
+
+.. code-block:: python
+
+ from cve_bin_tool.parsers.dart import DartParser
+ from cve_bin_tool.parsers.go import GoParser
+ from cve_bin_tool.parsers.java import JavaParser
+ from cve_bin_tool.parsers.javascript import JavascriptParser
+ from cve_bin_tool.parsers.perl import PerlParser
+ from cve_bin_tool.parsers.php import PhpParser
+ from cve_bin_tool.parsers.python import PythonParser, PythonRequirementsParser
+ from cve_bin_tool.parsers.r import RParser
+ from cve_bin_tool.parsers.ruby import RubyParser
+ from cve_bin_tool.parsers.rust import RustParser
+ from cve_bin_tool.parsers.swift import SwiftParser
+ from cve_bin_tool.parsers.bandit import BanditParser
+
+Setting Up a New Package and Entry Point
+----------------------------------------
+
+To implement a new parser plugin follow these steps:
+
+1. Create the Parser Class
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+First, create the parser class. This class should be located in the appropriate directory within your project. For example, you might place it in ``cve_bin_tool_parser_env/env.py``.
+
+.. literalinclude:: /../cve_bin_tool/parsers/env.py
+
+2. Set Up ``setup.py``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Next, configure the ``setup.py`` file boilerplate.
+
+.. literalinclude:: /../example/oot-parser/setup.py
+
+3. Set Up ``setup.cfg``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Next, configure the ``setup.cfg`` file to include your new parser as an entry point. This allows the parser to be dynamically discovered and used by the project.
+
+.. literalinclude:: /../example/oot-parser/setup_env.cfg
+
+4. Create ``entry_points.txt``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You may also need to configure an ``entry_points.txt`` file if your project uses it to manage entry points.
+
+.. literalinclude:: /../example/oot-parser/entry_points_env.txt
+
+5. Install your plugin
+^^^^^^^^^^^^^^^^^^^^^^
+
+You need to activate your virtualenv before installing if you set one up.
+
+.. code-block:: console
+
+ $ touch cve_bin_tool_parser_env/__init__.py
+ $ git init
+ $ python -m pip install -e .
+
+6. Populate the to-be-parsed file
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In this example we implemented the ``EnvParser`` which is the standard
+``/etc/environment`` style format, let's save the following as ``.env``.
+
+.. literalinclude:: /../test/parser_env_test_0001.env
+
+7. Run ``cve-bin-tool`` and see your plugin's findings
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Let's test that our defined CVE comes up by scanning a ``.env`` file.
+
+.. code-block:: console
+
+ $ cve-bin-tool --log debug .env
+
+Advanced Example: Ad-Hoc CVEs
+-----------------------------
+
+For more information see: https://github.com/ossf/wg-vulnerability-disclosures/issues/94
+
+1. Create the Parser Class
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+First, create the parser class. This class should be located in the appropriate directory within your project. For example, you might place it in ``cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py``.
+
+.. literalinclude:: /../example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py
+
+2. Set Up ``setup.py``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Next, configure the ``setup.py`` file boilerplate.
+
+.. literalinclude:: /../example/oot-parser/setup.py
+
+3. Set Up ``setup.cfg``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Next, configure the ``setup.cfg`` file to include your new parser as an entry point. This allows the parser to be dynamically discovered and used by the project.
+
+.. literalinclude:: /../example/oot-parser/setup.cfg
+
+4. Create ``entry_points.txt``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You may also need to configure an ``entry_points.txt`` file if your project uses it to manage entry points.
+
+.. literalinclude:: /../example/oot-parser/entry_points.txt
+
+5. Install your plugin
+^^^^^^^^^^^^^^^^^^^^^^
+
+You need to activate your virtualenv before installing if you set one up.
+
+.. code-block:: console
+
+ $ touch cve_bin_tool_parser_static_analysis_bandit/__init__.py
+ $ git init
+ $ python -m pip install -e .
+
+6. Run ``cve-bin-tool``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+In this example we implemented the ``BanditParser`` which is a static
+analysis tool for Python files. We'll test that it loads by scanning
+a ``.py`` file.
+
+.. code-block:: console
+
+ $ cve-bin-tool --format json --detail -- cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py
+
+7. View Findings
+^^^^^^^^^^^^^^^^
+
+Let's view our two findings, we need to decode the JSON stored in the
+description which will be an object describing the bug.
+
+.. code-block:: console
+
+ $ cat output.cve-bin-tool.*.json | jq '.[] | .description = (.description | fromjson)'
+
+.. code-block:: json
+
+ {
+ "vendor": "username:alice:platform:example.com",
+ "product": "filepath:example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py",
+ "version": "v0.0.0.dev-SomeShaValue-N-Other-Branches-Workload-ID-Scan-Number-2d8852cf-ebfd-4495-97e2-2ce23e4e557d",
+ "location": 11,
+ "cve_number": "CVE-0001-urn:ietf:params:scitt:statement:sha-256:base64url:5i6UeRzg1...0...qnGmr1o",
+ "severity": "LOW",
+ "score": "unknown",
+ "source": "SCITT_URN_FOR_MANIFEST_OF_EXECUTED_WORKFLOW_WITH_SARIF_OUTPUTS_DEREFERENCEABLE",
+ "cvss_version": "3",
+ "cvss_vector": "unknown",
+ "paths": "example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py",
+ "remarks": "NewFound",
+ "comments": "",
+ "description": {
+ "code": "10 import re\n11 import subprocess\n12 import sys\n",
+ "col_offset": 0,
+ "end_col_offset": 17,
+ "filename": "/home/alice/Documents/python/cve-bin-tool/example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py",
+ "issue_confidence": "HIGH",
+ "issue_cwe": {
+ "id": 78,
+ "link": "https://cwe.mitre.org/data/definitions/78.html"
+ },
+ "issue_severity": "LOW",
+ "issue_text": "Consider possible security implications associated with the subprocess module.",
+ "line_number": 11,
+ "line_range": [
+ 11
+ ],
+ "more_info": "https://bandit.readthedocs.io/en/1.7.8/blacklists/blacklist_imports.html#b404-import-subprocess",
+ "test_id": "B404",
+ "test_name": "blacklist"
+ }
+ }
+
+.. code-block:: json
+
+ {
+ "vendor": "username:alice:platform:example.com",
+ "product": "filepath:example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py",
+ "version": "v0.0.0.dev-SomeShaValue-N-Other-Branches-Workload-ID-Scan-Number-2d8852cf-ebfd-4495-97e2-2ce23e4e557d",
+ "location": 11,
+ "cve_number": "CVE-0001-urn:ietf:params:scitt:statement:sha-256:base64url:5i6UeRzg1...1...qnGmr1o",
+ "severity": "LOW",
+ "score": "unknown",
+ "source": "SCITT_URN_FOR_MANIFEST_OF_EXECUTED_WORKFLOW_WITH_SARIF_OUTPUTS_DEREFERENCEABLE",
+ "cvss_version": "3",
+ "cvss_vector": "unknown",
+ "paths": "example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py",
+ "remarks": "NewFound",
+ "comments": "",
+ "description": {
+ "code": "118 try:\n119 stdout = subprocess.check_output(\n120 cmd,\n121 )\n122 except subprocess.CalledProcessError as error:\n",
+ "col_offset": 21,
+ "end_col_offset": 13,
+ "filename": "/home/alice/Documents/python/cve-bin-tool/example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py",
+ "issue_confidence": "HIGH",
+ "issue_cwe": {
+ "id": 78,
+ "link": "https://cwe.mitre.org/data/definitions/78.html"
+ },
+ "issue_severity": "LOW",
+ "issue_text": "subprocess call - check for execution of untrusted input.",
+ "line_number": 119,
+ "line_range": [
+ 119,
+ 120,
+ 121
+ ],
+ "more_info": "https://bandit.readthedocs.io/en/1.7.8/plugins/b603_subprocess_without_shell_equals_true.html",
+ "test_id": "B603",
+ "test_name": "subprocess_without_shell_equals_true"
+ }
+ }
+
+Test Implementation
+-------------------
+
+A new test class `TestParsers` has been introduced to verify that the expected file types are correctly mapped to their respective parsers. The test ensures that the actual valid files match the expected valid files.
+
+Test Method
+^^^^^^^^^^^
+
+- `test_parser_match_filenames_results_in_correct_valid_files`: This test compares the `EXPECTED_VALID_FILES` dictionary with the `actual_valid_files` dictionary imported from `cve_bin_tool.parsers.parse`. If there is any discrepancy between the two, the test will fail, indicating that the loaded file types do not match the expected registered file types.
diff --git a/doc/index.rst b/doc/index.rst
index a0de036e1a..798c77d831 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -19,6 +19,7 @@ The CVE Binary Tool helps you determine if your system includes known vulnerabil
RELEASE.md
CONTRIBUTING.md
CHECKERS.md
+ PARSERS.rst
sboms_for_humans/README.md
new-contributor-tips.md
pypi_downloads.md
diff --git a/example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py b/example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py
new file mode 100644
index 0000000000..b49eb04ae1
--- /dev/null
+++ b/example/oot-parser/cve_bin_tool_parser_static_analysis_bandit/static_analysis_bandit.py
@@ -0,0 +1,203 @@
+# Copyright (C) 2024 Intel Corporation
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import annotations
+
+import dataclasses
+import json
+import os
+import pathlib
+import re
+import subprocess
+import sys
+import uuid
+
+import yaml
+from packageurl import PackageURL
+
+from cve_bin_tool.parsers import Parser
+from cve_bin_tool.util import ProductInfo, ScanInfo
+
+
+@dataclasses.dataclass
+class BanditNamespaceConfig:
+ ad_hoc_cve_id: str
+ vendor: str
+ product: str
+ version: str
+ location: str
+ description: str
+ severity: str
+ score: float
+
+
+@dataclasses.dataclass
+class BanditConfig:
+ namespaces: dict[str, BanditNamespaceConfig]
+
+
+class BanditParser(Parser):
+ """
+ Parser for Python requirements files.
+ This parser is designed to parse Python requirements files (usually named
+ requirements.txt) and generate PURLs (Package URLs) for the listed packages.
+ """
+
+ PARSER_MATCH_FILENAMES = [
+ ".py",
+ ]
+
+ @staticmethod
+ def parse_bandit_output(filename, contents):
+ username = os.environ.get("USER", "unknown-user")
+ config_gh_hosts_yaml_path = pathlib.Path(
+ "~", ".config", "gh", "hosts.yml"
+ ).expanduser()
+ if config_gh_hosts_yaml_path.exists():
+ # GitHub username if gh CLI installed
+ config_gh_hosts_yaml = yaml.safe_load(config_gh_hosts_yaml_path.read_text())
+ platform = "github.com"
+ username = config_gh_hosts_yaml[platform]["user"]
+ vendor = f"username:{username}:platform:{platform}"
+ product = f"filepath:{filename}"
+ version = f"v0.0.0.dev-SomeShaValue-N-Other-Branches-Workload-ID-Scan-Number-{uuid.uuid4()}"
+
+ contents = json.loads(contents)
+
+ errors = contents.get("errors", [])
+ if errors:
+ raise Exception(json.dumps(contents))
+
+ namespaces = {}
+ for i, result in enumerate(contents.get("results", [])):
+ # Version is the same when code at location matches code from output
+ result["issue_text"]
+ result["code"]
+
+ # TODO Replace UUID with with SCITT URN
+ # SCITT A.4.2
+ ad_hoc_cve_id = f"CVE-0001-urn:ietf:params:scitt:statement:sha-256:base64url:5i6UeRzg1...{i}...qnGmr1o"
+
+ # TODO Sort by something, line? Int of content address?
+ namespace = f"bandit-{i}"
+
+ # TODO Take vendor product and version automatically from git repo
+ # or installed pypi package meta-info.
+ namespaces[namespace] = BanditNamespaceConfig(
+ ad_hoc_cve_id=ad_hoc_cve_id,
+ vendor=vendor,
+ product=product,
+ version=version,
+ severity="LOW",
+ score=0.0,
+ location=result["line_number"],
+ description=json.dumps(result),
+ )
+ return BanditConfig(namespaces=namespaces)
+
+ def run_checker(self, filename):
+ """
+ Parse the .bandit file and yield ScanInfo objects for the listed packages.
+ Args:
+ filename (str): The path to the .bandit file.
+ Yields:
+ str: ScanInfo objects for the packages listed in the file.
+ """
+ file_path = pathlib.Path(filename).resolve()
+ cmd = [
+ sys.executable,
+ "-um",
+ "bandit",
+ "-f",
+ "json",
+ "--exit-zero",
+ "--",
+ # TODO Relative paths? Need top level directory being scanned
+ str(file_path),
+ ]
+ try:
+ stdout = subprocess.check_output(
+ cmd,
+ )
+ except subprocess.CalledProcessError as error:
+ raise Exception(error.stderr) from error
+
+ bandit_config = self.parse_bandit_output(filename, stdout)
+
+ # TODO Create SCITT_URN_FOR_MANIFEST_OF_EXECUTED_WORKFLOW_WITH_SARIF_OUTPUTS_DEREFERENCEABLE
+ # by making a request to the poligy engine and getting it's workflow
+ # manifest as output and deriving from that or extend it to return that.
+ data_source = "SCITT_URN_FOR_MANIFEST_OF_EXECUTED_WORKFLOW_WITH_SARIF_OUTPUTS_DEREFERENCEABLE"
+
+ affected_data = []
+ severity_data = []
+
+ for _namespace, cve in bandit_config.namespaces.items():
+ affected_data.append(
+ {
+ "cve_id": cve.ad_hoc_cve_id,
+ "vendor": cve.vendor,
+ "product": cve.product,
+ # TODO Version MUST be unique to this bug!
+ "version": cve.version,
+ "versionStartIncluding": "",
+ # "versionStartIncluding": cve.version,
+ "versionStartExcluding": "",
+ "versionEndIncluding": "",
+ # "versionEndIncluding": cve.version,
+ "versionEndExcluding": "",
+ }
+ )
+ severity_data.append(
+ {
+ "ID": cve.ad_hoc_cve_id,
+ # TODO severity
+ "severity": cve.severity,
+ # TODO description
+ "description": cve.description,
+ # TODO score
+ "score": 0,
+ # TODO CVSS_version
+ "CVSS_version": 3,
+ # TODO CVSS_vector
+ "CVSS_vector": "",
+ # TODO Ideally this comes from bisecting and pinpointing the
+ # bug's introduction to the codebase
+ "last_modified": "",
+ }
+ )
+
+ with self.cve_db.with_cursor() as cursor:
+ self.cve_db.populate_cve_metrics(severity_data, cursor)
+ self.cve_db.populate_severity(severity_data, cursor, data_source)
+ self.cve_db.populate_affected(affected_data, cursor, data_source)
+
+ product_infos = {}
+ for _namespace, cve in bandit_config.namespaces.items():
+ product_infos_key = (
+ cve.vendor,
+ cve.product,
+ cve.version,
+ )
+ product_infos.setdefault(
+ product_infos_key,
+ ProductInfo(
+ cve.vendor,
+ cve.product,
+ cve.version,
+ cve.location,
+ PackageURL(
+ type="ad-hoc",
+ namespace=cve.vendor,
+ name=re.sub(r"[^a-zA-Z0-9._-]", "", cve.product).lower(),
+ version=cve.version,
+ qualifiers={},
+ subpath=None,
+ ),
+ ),
+ )
+ product_info = product_infos[product_infos_key]
+ for _namespace, cve in bandit_config.namespaces.items():
+ yield ScanInfo(product_info, pathlib.Path(filename).resolve())
+
+ # TODO VEX attached via linked data to ad-hoc CVE-ID
diff --git a/example/oot-parser/entry_points.txt b/example/oot-parser/entry_points.txt
new file mode 100644
index 0000000000..a1275e8972
--- /dev/null
+++ b/example/oot-parser/entry_points.txt
@@ -0,0 +1,2 @@
+[cve_bin_tool.parsers]
+static_analysis_bandit = cve_bin_tool_parser_static_analysis_bandit.static_analysis_bandit:BanditParser
diff --git a/example/oot-parser/entry_points_env.txt b/example/oot-parser/entry_points_env.txt
new file mode 100644
index 0000000000..5efda540bf
--- /dev/null
+++ b/example/oot-parser/entry_points_env.txt
@@ -0,0 +1,2 @@
+[cve_bin_tool.parsers]
+env = cve_bin_tool_parser_env.env:EnvParser
diff --git a/example/oot-parser/setup.cfg b/example/oot-parser/setup.cfg
new file mode 100644
index 0000000000..77ded2c4b5
--- /dev/null
+++ b/example/oot-parser/setup.cfg
@@ -0,0 +1,10 @@
+[metadata]
+name = cve-bin-tool-parser-static-analysis-bandit
+version = 1.0.0
+description = CVE Binary Tool: Parser: Static Analysis: Bandit
+
+[options]
+packages = find:
+entry_points = file: entry_points.txt
+setup_requires =
+ setuptools_scm[toml]>=3.4.3
diff --git a/example/oot-parser/setup.py b/example/oot-parser/setup.py
new file mode 100644
index 0000000000..d102c58907
--- /dev/null
+++ b/example/oot-parser/setup.py
@@ -0,0 +1,9 @@
+import site
+import sys
+
+import setuptools
+
+# See https://github.com/pypa/pip/issues/7953
+site.ENABLE_USER_SITE = "--user" in sys.argv[1:]
+
+setuptools.setup(use_scm_version=True)
diff --git a/example/oot-parser/setup_env.cfg b/example/oot-parser/setup_env.cfg
new file mode 100644
index 0000000000..1ddcc812c7
--- /dev/null
+++ b/example/oot-parser/setup_env.cfg
@@ -0,0 +1,10 @@
+[metadata]
+name = cve-bin-tool-parser-env
+version = 1.0.0
+description = CVE Binary Tool: Parser: .env
+
+[options]
+packages = find:
+entry_points = file: entry_points.txt
+setup_requires =
+ setuptools_scm[toml]>=3.4.3
diff --git a/requirements.csv b/requirements.csv
index 3ac40cc600..763e346f29 100644
--- a/requirements.csv
+++ b/requirements.csv
@@ -21,5 +21,6 @@ python_not_in_db,packaging
python_not_in_db,importlib_resources
vsajip_not_in_db,python-gnupg
anthonyharrison_not_in_db,lib4sbom
+anthonyharrison_not_in_db,lib4vex
the_purl_authors_not_in_db,packageurl-python
h2non,filetype
diff --git a/requirements.txt b/requirements.txt
index f451373438..5ceb406231 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,12 +10,13 @@ importlib_resources; python_version < "3.9"
jinja2>=2.11.3
jsonschema>=3.0.2
lib4sbom>=0.7.0
+lib4vex>=0.1.0
python-gnupg
packageurl-python
packaging
plotly
pyyaml>=5.4
-requests
+requests>=2.32.0
rich
rpmfile>=1.0.6
toml; python_version < "3.11"
diff --git a/sbom/cve-bin-tool-py3.10.json b/sbom/cve-bin-tool-py3.10.json
index a9f90448d4..374552746d 100644
--- a/sbom/cve-bin-tool-py3.10.json
+++ b/sbom/cve-bin-tool-py3.10.json
@@ -2,10 +2,10 @@
"$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.6",
- "serialNumber": "urn:uuid:6f0a7ce7-de20-4120-9766-3f133c57ee38",
+ "serialNumber": "urn:uuid:fdd5bd8b-7688-4584-9c00-033ea7aefded",
"version": 1,
"metadata": {
- "timestamp": "2024-05-20T00:28:21Z",
+ "timestamp": "2024-06-17T00:29:56Z",
"tools": {
"components": [
{
@@ -658,7 +658,7 @@
"type": "library",
"bom-ref": "16-gsutil",
"name": "gsutil",
- "version": "5.29",
+ "version": "5.30",
"supplier": {
"name": "Google Inc .",
"contact": [
@@ -667,7 +667,7 @@
}
]
},
- "cpe": "cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*",
"description": "A command line tool for interacting with cloud storage services.",
"licenses": [
{
@@ -679,12 +679,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/gsutil/5.29",
+ "url": "https://pypi.org/project/gsutil/5.30",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/gsutil@5.29",
+ "purl": "pkg:pypi/gsutil@5.30",
"properties": [
{
"name": "language",
@@ -700,7 +700,7 @@
"type": "library",
"bom-ref": "17-argcomplete",
"name": "argcomplete",
- "version": "3.3.0",
+ "version": "3.4.0",
"supplier": {
"name": "Andrey Kislyuk",
"contact": [
@@ -709,14 +709,8 @@
}
]
},
- "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*",
"description": "Bash tab completion for argparse",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "c7cc834df1fddcf94bd35b740fef7c7ab8e9c350"
- }
- ],
"licenses": [
{
"license": {
@@ -727,12 +721,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/argcomplete/3.3.0",
+ "url": "https://pypi.org/project/argcomplete/3.4.0",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/argcomplete@3.3.0",
+ "purl": "pkg:pypi/argcomplete@3.4.0",
"properties": [
{
"name": "language",
@@ -1520,7 +1514,7 @@
"type": "library",
"bom-ref": "35-cryptography",
"name": "cryptography",
- "version": "42.0.7",
+ "version": "42.0.8",
"supplier": {
"name": "The Python Cryptographic Authority and individual contributors",
"contact": [
@@ -1529,7 +1523,7 @@
}
]
},
- "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*",
"description": "cryptography is a package which provides cryptographic recipes and primitives to Python developers.",
"licenses": [
{
@@ -1538,12 +1532,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/cryptography/42.0.7",
+ "url": "https://pypi.org/project/cryptography/42.0.8",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/cryptography@42.0.7",
+ "purl": "pkg:pypi/cryptography@42.0.8",
"properties": [
{
"name": "language",
@@ -2153,18 +2147,12 @@
"type": "library",
"bom-ref": "50-packageurl-python",
"name": "packageurl-python",
- "version": "0.15.0",
+ "version": "0.15.1",
"supplier": {
"name": "the purl authors"
},
- "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*",
"description": "A purl aka. Package URL parser and builder",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "a46d42493bbb7ae1a227be7bbd6b180a149ad3b1"
- }
- ],
"licenses": [
{
"license": {
@@ -2175,12 +2163,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/packageurl-python/0.15.0",
+ "url": "https://pypi.org/project/packageurl-python/0.15.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packageurl-python@0.15.0",
+ "purl": "pkg:pypi/packageurl-python@0.15.1",
"properties": [
{
"name": "language",
@@ -2196,7 +2184,7 @@
"type": "library",
"bom-ref": "51-packaging",
"name": "packaging",
- "version": "24.0",
+ "version": "24.1",
"supplier": {
"name": "Donald Stufft",
"contact": [
@@ -2205,16 +2193,16 @@
}
]
},
- "cpe": "cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*",
"description": "Core utilities for Python packages",
"externalReferences": [
{
- "url": "https://pypi.org/project/packaging/24.0",
+ "url": "https://pypi.org/project/packaging/24.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packaging@24.0",
+ "purl": "pkg:pypi/packaging@24.1",
"properties": [
{
"name": "language",
@@ -2362,7 +2350,7 @@
"type": "library",
"bom-ref": "55-requests",
"name": "requests",
- "version": "2.31.0",
+ "version": "2.32.3",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2371,14 +2359,8 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*",
"description": "Python HTTP for Humans.",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4"
- }
- ],
"licenses": [
{
"license": {
@@ -2389,12 +2371,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/requests/2.31.0",
+ "url": "https://pypi.org/project/requests/2.32.3",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/requests@2.31.0",
+ "purl": "pkg:pypi/requests@2.32.3",
"properties": [
{
"name": "language",
@@ -2410,7 +2392,7 @@
"type": "library",
"bom-ref": "56-certifi",
"name": "certifi",
- "version": "2024.2.2",
+ "version": "2024.6.2",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2419,7 +2401,7 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*",
"description": "Python package for providing Mozilla's CA Bundle.",
"licenses": [
{
@@ -2431,12 +2413,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/certifi/2024.2.2",
+ "url": "https://pypi.org/project/certifi/2024.6.2",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/certifi@2024.2.2",
+ "purl": "pkg:pypi/certifi@2024.6.2",
"properties": [
{
"name": "language",
@@ -2667,6 +2649,12 @@
},
"cpe": "cpe:2.3:a:georg_brandl:pygments:2.18.0:*:*:*:*:*:*:*",
"description": "Pygments is a syntax highlighting package written in Python.",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb"
+ }
+ ],
"licenses": [
{
"license": {
diff --git a/sbom/cve-bin-tool-py3.10.spdx b/sbom/cve-bin-tool-py3.10.spdx
index 8749d0f52c..96f2713fb1 100644
--- a/sbom/cve-bin-tool-py3.10.spdx
+++ b/sbom/cve-bin-tool-py3.10.spdx
@@ -2,10 +2,10 @@ SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: Python-cve-bin-tool
-DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-68475ad9-59ac-45a0-aa18-f5fada8c42c1
+DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-9179648e-c093-4e62-a89f-7a99325df79e
LicenseListVersion: 3.22
Creator: Tool: sbom4python-0.10.4
-Created: 2024-05-20T00:26:49Z
+Created: 2024-06-17T00:28:35Z
CreatorComment: This document has been automatically generated.
#####
@@ -250,35 +250,34 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:tomas_aparicio:filetype:1.2.0:*:*:*:*:
PackageName: gsutil
SPDXID: SPDXRef-Package-16-gsutil
-PackageVersion: 5.29
+PackageVersion: 5.30
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Google Inc. (buganizer-system+187143@google.com)
-PackageDownloadLocation: https://pypi.org/project/gsutil/5.29
+PackageDownloadLocation: https://pypi.org/project/gsutil/5.30
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: gsutil declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: A command line tool for interacting with cloud storage services.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.29
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.30
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*
#####
PackageName: argcomplete
SPDXID: SPDXRef-Package-17-argcomplete
-PackageVersion: 3.3.0
+PackageVersion: 3.4.0
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Andrey Kislyuk (kislyuk@gmail.com)
-PackageDownloadLocation: https://pypi.org/project/argcomplete/3.3.0
+PackageDownloadLocation: https://pypi.org/project/argcomplete/3.4.0
FilesAnalyzed: false
-PackageChecksum: SHA1: c7cc834df1fddcf94bd35b740fef7c7ab8e9c350
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: argcomplete declares Apache Software License which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Bash tab completion for argparse
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.3.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.4.0
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*
#####
PackageName: crcmod
@@ -558,17 +557,17 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_pyopenssl_developers:pyopenssl:24.
PackageName: cryptography
SPDXID: SPDXRef-Package-35-cryptography
-PackageVersion: 42.0.7
+PackageVersion: 42.0.8
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Organization: The Python Cryptographic Authority and individual contributors (cryptography-dev@python.org)
-PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.7
+PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.8
FilesAnalyzed: false
PackageLicenseDeclared: Apache-2.0 OR BSD-3-Clause
PackageLicenseConcluded: Apache-2.0 OR BSD-3-Clause
PackageCopyrightText: NOASSERTION
PackageSummary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.7
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.8
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*
#####
PackageName: cffi
@@ -794,33 +793,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:raphael_barrois:semantic-version:2.10.
PackageName: packageurl-python
SPDXID: SPDXRef-Package-50-packageurl-python
-PackageVersion: 0.15.0
+PackageVersion: 0.15.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: the purl authors
-PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.0
+PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.1
FilesAnalyzed: false
-PackageChecksum: SHA1: a46d42493bbb7ae1a227be7bbd6b180a149ad3b1
PackageLicenseDeclared: MIT
PackageLicenseConcluded: MIT
PackageCopyrightText: NOASSERTION
PackageSummary: A purl aka. Package URL parser and builder
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*
#####
PackageName: packaging
SPDXID: SPDXRef-Package-51-packaging
-PackageVersion: 24.0
+PackageVersion: 24.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Donald Stufft (donald@stufft.io)
-PackageDownloadLocation: https://pypi.org/project/packaging/24.0
+PackageDownloadLocation: https://pypi.org/project/packaging/24.1
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageSummary: Core utilities for Python packages
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*
#####
PackageName: plotly
@@ -873,34 +871,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:vinay_sajip:python-gnupg:0.5.2:*:*:*:*
PackageName: requests
SPDXID: SPDXRef-Package-55-requests
-PackageVersion: 2.31.0
+PackageVersion: 2.32.3
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.org)
-PackageDownloadLocation: https://pypi.org/project/requests/2.31.0
+PackageDownloadLocation: https://pypi.org/project/requests/2.32.3
FilesAnalyzed: false
-PackageChecksum: SHA1: 147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4
-PackageLicenseDeclared: NOASSERTION
+PackageLicenseDeclared: Apache-2.0
PackageLicenseConcluded: Apache-2.0
-PackageLicenseComments: requests declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Python HTTP for Humans.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.31.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.32.3
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*
#####
PackageName: certifi
SPDXID: SPDXRef-Package-56-certifi
-PackageVersion: 2024.2.2
+PackageVersion: 2024.6.2
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.com)
-PackageDownloadLocation: https://pypi.org/project/certifi/2024.2.2
+PackageDownloadLocation: https://pypi.org/project/certifi/2024.6.2
FilesAnalyzed: false
PackageLicenseDeclared: MPL-2.0
PackageLicenseConcluded: MPL-2.0
PackageCopyrightText: NOASSERTION
PackageSummary: Python package for providing Mozilla's CA Bundle.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.2.2
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.6.2
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*
#####
PackageName: charset-normalizer
@@ -988,6 +984,7 @@ PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Georg Brandl (georg@python.org)
PackageDownloadLocation: https://pypi.org/project/Pygments/2.18.0
FilesAnalyzed: false
+PackageChecksum: SHA1: d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb
PackageLicenseDeclared: BSD-2-Clause
PackageLicenseConcluded: BSD-2-Clause
PackageCopyrightText: NOASSERTION
diff --git a/sbom/cve-bin-tool-py3.11.json b/sbom/cve-bin-tool-py3.11.json
index 910eafe3d3..2f6e84bf0e 100644
--- a/sbom/cve-bin-tool-py3.11.json
+++ b/sbom/cve-bin-tool-py3.11.json
@@ -2,10 +2,10 @@
"$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.6",
- "serialNumber": "urn:uuid:2517bccd-0e14-4a43-8f1c-68ee87099e0f",
+ "serialNumber": "urn:uuid:3658abd9-6823-4e3c-ac3d-3494bd9e79a7",
"version": 1,
"metadata": {
- "timestamp": "2024-05-20T00:28:17Z",
+ "timestamp": "2024-06-17T00:29:53Z",
"tools": {
"components": [
{
@@ -610,7 +610,7 @@
"type": "library",
"bom-ref": "15-gsutil",
"name": "gsutil",
- "version": "5.29",
+ "version": "5.30",
"supplier": {
"name": "Google Inc .",
"contact": [
@@ -619,7 +619,7 @@
}
]
},
- "cpe": "cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*",
"description": "A command line tool for interacting with cloud storage services.",
"licenses": [
{
@@ -631,12 +631,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/gsutil/5.29",
+ "url": "https://pypi.org/project/gsutil/5.30",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/gsutil@5.29",
+ "purl": "pkg:pypi/gsutil@5.30",
"properties": [
{
"name": "language",
@@ -652,7 +652,7 @@
"type": "library",
"bom-ref": "16-argcomplete",
"name": "argcomplete",
- "version": "3.3.0",
+ "version": "3.4.0",
"supplier": {
"name": "Andrey Kislyuk",
"contact": [
@@ -661,14 +661,8 @@
}
]
},
- "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*",
"description": "Bash tab completion for argparse",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "c7cc834df1fddcf94bd35b740fef7c7ab8e9c350"
- }
- ],
"licenses": [
{
"license": {
@@ -679,12 +673,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/argcomplete/3.3.0",
+ "url": "https://pypi.org/project/argcomplete/3.4.0",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/argcomplete@3.3.0",
+ "purl": "pkg:pypi/argcomplete@3.4.0",
"properties": [
{
"name": "language",
@@ -1472,7 +1466,7 @@
"type": "library",
"bom-ref": "34-cryptography",
"name": "cryptography",
- "version": "42.0.7",
+ "version": "42.0.8",
"supplier": {
"name": "The Python Cryptographic Authority and individual contributors",
"contact": [
@@ -1481,7 +1475,7 @@
}
]
},
- "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*",
"description": "cryptography is a package which provides cryptographic recipes and primitives to Python developers.",
"licenses": [
{
@@ -1490,12 +1484,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/cryptography/42.0.7",
+ "url": "https://pypi.org/project/cryptography/42.0.8",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/cryptography@42.0.7",
+ "purl": "pkg:pypi/cryptography@42.0.8",
"properties": [
{
"name": "language",
@@ -2105,18 +2099,12 @@
"type": "library",
"bom-ref": "49-packageurl-python",
"name": "packageurl-python",
- "version": "0.15.0",
+ "version": "0.15.1",
"supplier": {
"name": "the purl authors"
},
- "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*",
"description": "A purl aka. Package URL parser and builder",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "a46d42493bbb7ae1a227be7bbd6b180a149ad3b1"
- }
- ],
"licenses": [
{
"license": {
@@ -2127,12 +2115,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/packageurl-python/0.15.0",
+ "url": "https://pypi.org/project/packageurl-python/0.15.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packageurl-python@0.15.0",
+ "purl": "pkg:pypi/packageurl-python@0.15.1",
"properties": [
{
"name": "language",
@@ -2148,7 +2136,7 @@
"type": "library",
"bom-ref": "50-packaging",
"name": "packaging",
- "version": "24.0",
+ "version": "24.1",
"supplier": {
"name": "Donald Stufft",
"contact": [
@@ -2157,16 +2145,16 @@
}
]
},
- "cpe": "cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*",
"description": "Core utilities for Python packages",
"externalReferences": [
{
- "url": "https://pypi.org/project/packaging/24.0",
+ "url": "https://pypi.org/project/packaging/24.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packaging@24.0",
+ "purl": "pkg:pypi/packaging@24.1",
"properties": [
{
"name": "language",
@@ -2314,7 +2302,7 @@
"type": "library",
"bom-ref": "54-requests",
"name": "requests",
- "version": "2.31.0",
+ "version": "2.32.3",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2323,14 +2311,8 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*",
"description": "Python HTTP for Humans.",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4"
- }
- ],
"licenses": [
{
"license": {
@@ -2341,12 +2323,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/requests/2.31.0",
+ "url": "https://pypi.org/project/requests/2.32.3",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/requests@2.31.0",
+ "purl": "pkg:pypi/requests@2.32.3",
"properties": [
{
"name": "language",
@@ -2362,7 +2344,7 @@
"type": "library",
"bom-ref": "55-certifi",
"name": "certifi",
- "version": "2024.2.2",
+ "version": "2024.6.2",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2371,7 +2353,7 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*",
"description": "Python package for providing Mozilla's CA Bundle.",
"licenses": [
{
@@ -2383,12 +2365,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/certifi/2024.2.2",
+ "url": "https://pypi.org/project/certifi/2024.6.2",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/certifi@2024.2.2",
+ "purl": "pkg:pypi/certifi@2024.6.2",
"properties": [
{
"name": "language",
@@ -2619,6 +2601,12 @@
},
"cpe": "cpe:2.3:a:georg_brandl:pygments:2.18.0:*:*:*:*:*:*:*",
"description": "Pygments is a syntax highlighting package written in Python.",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb"
+ }
+ ],
"licenses": [
{
"license": {
diff --git a/sbom/cve-bin-tool-py3.11.spdx b/sbom/cve-bin-tool-py3.11.spdx
index b0801539dc..d3ab26d2b9 100644
--- a/sbom/cve-bin-tool-py3.11.spdx
+++ b/sbom/cve-bin-tool-py3.11.spdx
@@ -2,10 +2,10 @@ SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: Python-cve-bin-tool
-DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-a18e0454-728e-4a13-8cfd-68e27dec2387
+DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-8b15b17c-175a-47f3-a368-d98a6b7def6f
LicenseListVersion: 3.22
Creator: Tool: sbom4python-0.10.4
-Created: 2024-05-20T00:26:55Z
+Created: 2024-06-17T00:28:32Z
CreatorComment: This document has been automatically generated.
#####
@@ -233,35 +233,34 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:tomas_aparicio:filetype:1.2.0:*:*:*:*:
PackageName: gsutil
SPDXID: SPDXRef-Package-15-gsutil
-PackageVersion: 5.29
+PackageVersion: 5.30
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Google Inc. (buganizer-system+187143@google.com)
-PackageDownloadLocation: https://pypi.org/project/gsutil/5.29
+PackageDownloadLocation: https://pypi.org/project/gsutil/5.30
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: gsutil declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: A command line tool for interacting with cloud storage services.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.29
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.30
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*
#####
PackageName: argcomplete
SPDXID: SPDXRef-Package-16-argcomplete
-PackageVersion: 3.3.0
+PackageVersion: 3.4.0
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Andrey Kislyuk (kislyuk@gmail.com)
-PackageDownloadLocation: https://pypi.org/project/argcomplete/3.3.0
+PackageDownloadLocation: https://pypi.org/project/argcomplete/3.4.0
FilesAnalyzed: false
-PackageChecksum: SHA1: c7cc834df1fddcf94bd35b740fef7c7ab8e9c350
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: argcomplete declares Apache Software License which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Bash tab completion for argparse
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.3.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.4.0
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*
#####
PackageName: crcmod
@@ -541,17 +540,17 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_pyopenssl_developers:pyopenssl:24.
PackageName: cryptography
SPDXID: SPDXRef-Package-34-cryptography
-PackageVersion: 42.0.7
+PackageVersion: 42.0.8
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Organization: The Python Cryptographic Authority and individual contributors (cryptography-dev@python.org)
-PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.7
+PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.8
FilesAnalyzed: false
PackageLicenseDeclared: Apache-2.0 OR BSD-3-Clause
PackageLicenseConcluded: Apache-2.0 OR BSD-3-Clause
PackageCopyrightText: NOASSERTION
PackageSummary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.7
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.8
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*
#####
PackageName: cffi
@@ -777,33 +776,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:raphael_barrois:semantic-version:2.10.
PackageName: packageurl-python
SPDXID: SPDXRef-Package-49-packageurl-python
-PackageVersion: 0.15.0
+PackageVersion: 0.15.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: the purl authors
-PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.0
+PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.1
FilesAnalyzed: false
-PackageChecksum: SHA1: a46d42493bbb7ae1a227be7bbd6b180a149ad3b1
PackageLicenseDeclared: MIT
PackageLicenseConcluded: MIT
PackageCopyrightText: NOASSERTION
PackageSummary: A purl aka. Package URL parser and builder
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*
#####
PackageName: packaging
SPDXID: SPDXRef-Package-50-packaging
-PackageVersion: 24.0
+PackageVersion: 24.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Donald Stufft (donald@stufft.io)
-PackageDownloadLocation: https://pypi.org/project/packaging/24.0
+PackageDownloadLocation: https://pypi.org/project/packaging/24.1
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageSummary: Core utilities for Python packages
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*
#####
PackageName: plotly
@@ -856,34 +854,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:vinay_sajip:python-gnupg:0.5.2:*:*:*:*
PackageName: requests
SPDXID: SPDXRef-Package-54-requests
-PackageVersion: 2.31.0
+PackageVersion: 2.32.3
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.org)
-PackageDownloadLocation: https://pypi.org/project/requests/2.31.0
+PackageDownloadLocation: https://pypi.org/project/requests/2.32.3
FilesAnalyzed: false
-PackageChecksum: SHA1: 147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4
-PackageLicenseDeclared: NOASSERTION
+PackageLicenseDeclared: Apache-2.0
PackageLicenseConcluded: Apache-2.0
-PackageLicenseComments: requests declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Python HTTP for Humans.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.31.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.32.3
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*
#####
PackageName: certifi
SPDXID: SPDXRef-Package-55-certifi
-PackageVersion: 2024.2.2
+PackageVersion: 2024.6.2
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.com)
-PackageDownloadLocation: https://pypi.org/project/certifi/2024.2.2
+PackageDownloadLocation: https://pypi.org/project/certifi/2024.6.2
FilesAnalyzed: false
PackageLicenseDeclared: MPL-2.0
PackageLicenseConcluded: MPL-2.0
PackageCopyrightText: NOASSERTION
PackageSummary: Python package for providing Mozilla's CA Bundle.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.2.2
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.6.2
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*
#####
PackageName: charset-normalizer
@@ -971,6 +967,7 @@ PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Georg Brandl (georg@python.org)
PackageDownloadLocation: https://pypi.org/project/Pygments/2.18.0
FilesAnalyzed: false
+PackageChecksum: SHA1: d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb
PackageLicenseDeclared: BSD-2-Clause
PackageLicenseConcluded: BSD-2-Clause
PackageCopyrightText: NOASSERTION
diff --git a/sbom/cve-bin-tool-py3.12.json b/sbom/cve-bin-tool-py3.12.json
index ab639e5e2b..3cd247af8a 100644
--- a/sbom/cve-bin-tool-py3.12.json
+++ b/sbom/cve-bin-tool-py3.12.json
@@ -2,10 +2,10 @@
"$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.6",
- "serialNumber": "urn:uuid:e52a72f9-0181-4811-92a1-ce5cae9eb918",
+ "serialNumber": "urn:uuid:85555e04-810c-469e-b65b-0e68cb8a0c82",
"version": 1,
"metadata": {
- "timestamp": "2024-05-20T00:28:19Z",
+ "timestamp": "2024-06-17T00:29:54Z",
"tools": {
"components": [
{
@@ -610,7 +610,7 @@
"type": "library",
"bom-ref": "15-gsutil",
"name": "gsutil",
- "version": "5.29",
+ "version": "5.30",
"supplier": {
"name": "Google Inc .",
"contact": [
@@ -619,7 +619,7 @@
}
]
},
- "cpe": "cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*",
"description": "A command line tool for interacting with cloud storage services.",
"licenses": [
{
@@ -631,12 +631,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/gsutil/5.29",
+ "url": "https://pypi.org/project/gsutil/5.30",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/gsutil@5.29",
+ "purl": "pkg:pypi/gsutil@5.30",
"properties": [
{
"name": "language",
@@ -652,7 +652,7 @@
"type": "library",
"bom-ref": "16-argcomplete",
"name": "argcomplete",
- "version": "3.3.0",
+ "version": "3.4.0",
"supplier": {
"name": "Andrey Kislyuk",
"contact": [
@@ -661,14 +661,8 @@
}
]
},
- "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*",
"description": "Bash tab completion for argparse",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "c7cc834df1fddcf94bd35b740fef7c7ab8e9c350"
- }
- ],
"licenses": [
{
"license": {
@@ -679,12 +673,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/argcomplete/3.3.0",
+ "url": "https://pypi.org/project/argcomplete/3.4.0",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/argcomplete@3.3.0",
+ "purl": "pkg:pypi/argcomplete@3.4.0",
"properties": [
{
"name": "language",
@@ -1472,7 +1466,7 @@
"type": "library",
"bom-ref": "34-cryptography",
"name": "cryptography",
- "version": "42.0.7",
+ "version": "42.0.8",
"supplier": {
"name": "The Python Cryptographic Authority and individual contributors",
"contact": [
@@ -1481,7 +1475,7 @@
}
]
},
- "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*",
"description": "cryptography is a package which provides cryptographic recipes and primitives to Python developers.",
"licenses": [
{
@@ -1490,12 +1484,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/cryptography/42.0.7",
+ "url": "https://pypi.org/project/cryptography/42.0.8",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/cryptography@42.0.7",
+ "purl": "pkg:pypi/cryptography@42.0.8",
"properties": [
{
"name": "language",
@@ -2105,18 +2099,12 @@
"type": "library",
"bom-ref": "49-packageurl-python",
"name": "packageurl-python",
- "version": "0.15.0",
+ "version": "0.15.1",
"supplier": {
"name": "the purl authors"
},
- "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*",
"description": "A purl aka. Package URL parser and builder",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "a46d42493bbb7ae1a227be7bbd6b180a149ad3b1"
- }
- ],
"licenses": [
{
"license": {
@@ -2127,12 +2115,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/packageurl-python/0.15.0",
+ "url": "https://pypi.org/project/packageurl-python/0.15.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packageurl-python@0.15.0",
+ "purl": "pkg:pypi/packageurl-python@0.15.1",
"properties": [
{
"name": "language",
@@ -2148,7 +2136,7 @@
"type": "library",
"bom-ref": "50-packaging",
"name": "packaging",
- "version": "24.0",
+ "version": "24.1",
"supplier": {
"name": "Donald Stufft",
"contact": [
@@ -2157,16 +2145,16 @@
}
]
},
- "cpe": "cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*",
"description": "Core utilities for Python packages",
"externalReferences": [
{
- "url": "https://pypi.org/project/packaging/24.0",
+ "url": "https://pypi.org/project/packaging/24.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packaging@24.0",
+ "purl": "pkg:pypi/packaging@24.1",
"properties": [
{
"name": "language",
@@ -2314,7 +2302,7 @@
"type": "library",
"bom-ref": "54-requests",
"name": "requests",
- "version": "2.31.0",
+ "version": "2.32.3",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2323,14 +2311,8 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*",
"description": "Python HTTP for Humans.",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4"
- }
- ],
"licenses": [
{
"license": {
@@ -2341,12 +2323,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/requests/2.31.0",
+ "url": "https://pypi.org/project/requests/2.32.3",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/requests@2.31.0",
+ "purl": "pkg:pypi/requests@2.32.3",
"properties": [
{
"name": "language",
@@ -2362,7 +2344,7 @@
"type": "library",
"bom-ref": "55-certifi",
"name": "certifi",
- "version": "2024.2.2",
+ "version": "2024.6.2",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2371,7 +2353,7 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*",
"description": "Python package for providing Mozilla's CA Bundle.",
"licenses": [
{
@@ -2383,12 +2365,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/certifi/2024.2.2",
+ "url": "https://pypi.org/project/certifi/2024.6.2",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/certifi@2024.2.2",
+ "purl": "pkg:pypi/certifi@2024.6.2",
"properties": [
{
"name": "language",
@@ -2619,6 +2601,12 @@
},
"cpe": "cpe:2.3:a:georg_brandl:pygments:2.18.0:*:*:*:*:*:*:*",
"description": "Pygments is a syntax highlighting package written in Python.",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb"
+ }
+ ],
"licenses": [
{
"license": {
diff --git a/sbom/cve-bin-tool-py3.12.spdx b/sbom/cve-bin-tool-py3.12.spdx
index ebd540efc9..6b068b03e4 100644
--- a/sbom/cve-bin-tool-py3.12.spdx
+++ b/sbom/cve-bin-tool-py3.12.spdx
@@ -2,10 +2,10 @@ SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: Python-cve-bin-tool
-DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-380fd52e-fd13-4c41-85ad-db0debb506fd
+DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-9da58dae-3be1-4751-b875-9e4a4b8a9266
LicenseListVersion: 3.22
Creator: Tool: sbom4python-0.10.4
-Created: 2024-05-20T00:26:49Z
+Created: 2024-06-17T00:28:35Z
CreatorComment: This document has been automatically generated.
#####
@@ -233,35 +233,34 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:tomas_aparicio:filetype:1.2.0:*:*:*:*:
PackageName: gsutil
SPDXID: SPDXRef-Package-15-gsutil
-PackageVersion: 5.29
+PackageVersion: 5.30
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Google Inc. (buganizer-system+187143@google.com)
-PackageDownloadLocation: https://pypi.org/project/gsutil/5.29
+PackageDownloadLocation: https://pypi.org/project/gsutil/5.30
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: gsutil declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: A command line tool for interacting with cloud storage services.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.29
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.30
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*
#####
PackageName: argcomplete
SPDXID: SPDXRef-Package-16-argcomplete
-PackageVersion: 3.3.0
+PackageVersion: 3.4.0
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Andrey Kislyuk (kislyuk@gmail.com)
-PackageDownloadLocation: https://pypi.org/project/argcomplete/3.3.0
+PackageDownloadLocation: https://pypi.org/project/argcomplete/3.4.0
FilesAnalyzed: false
-PackageChecksum: SHA1: c7cc834df1fddcf94bd35b740fef7c7ab8e9c350
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: argcomplete declares Apache Software License which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Bash tab completion for argparse
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.3.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.4.0
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*
#####
PackageName: crcmod
@@ -541,17 +540,17 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_pyopenssl_developers:pyopenssl:24.
PackageName: cryptography
SPDXID: SPDXRef-Package-34-cryptography
-PackageVersion: 42.0.7
+PackageVersion: 42.0.8
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Organization: The Python Cryptographic Authority and individual contributors (cryptography-dev@python.org)
-PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.7
+PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.8
FilesAnalyzed: false
PackageLicenseDeclared: Apache-2.0 OR BSD-3-Clause
PackageLicenseConcluded: Apache-2.0 OR BSD-3-Clause
PackageCopyrightText: NOASSERTION
PackageSummary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.7
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.8
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*
#####
PackageName: cffi
@@ -777,33 +776,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:raphael_barrois:semantic-version:2.10.
PackageName: packageurl-python
SPDXID: SPDXRef-Package-49-packageurl-python
-PackageVersion: 0.15.0
+PackageVersion: 0.15.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: the purl authors
-PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.0
+PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.1
FilesAnalyzed: false
-PackageChecksum: SHA1: a46d42493bbb7ae1a227be7bbd6b180a149ad3b1
PackageLicenseDeclared: MIT
PackageLicenseConcluded: MIT
PackageCopyrightText: NOASSERTION
PackageSummary: A purl aka. Package URL parser and builder
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*
#####
PackageName: packaging
SPDXID: SPDXRef-Package-50-packaging
-PackageVersion: 24.0
+PackageVersion: 24.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Donald Stufft (donald@stufft.io)
-PackageDownloadLocation: https://pypi.org/project/packaging/24.0
+PackageDownloadLocation: https://pypi.org/project/packaging/24.1
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageSummary: Core utilities for Python packages
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*
#####
PackageName: plotly
@@ -856,34 +854,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:vinay_sajip:python-gnupg:0.5.2:*:*:*:*
PackageName: requests
SPDXID: SPDXRef-Package-54-requests
-PackageVersion: 2.31.0
+PackageVersion: 2.32.3
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.org)
-PackageDownloadLocation: https://pypi.org/project/requests/2.31.0
+PackageDownloadLocation: https://pypi.org/project/requests/2.32.3
FilesAnalyzed: false
-PackageChecksum: SHA1: 147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4
-PackageLicenseDeclared: NOASSERTION
+PackageLicenseDeclared: Apache-2.0
PackageLicenseConcluded: Apache-2.0
-PackageLicenseComments: requests declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Python HTTP for Humans.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.31.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.32.3
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*
#####
PackageName: certifi
SPDXID: SPDXRef-Package-55-certifi
-PackageVersion: 2024.2.2
+PackageVersion: 2024.6.2
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.com)
-PackageDownloadLocation: https://pypi.org/project/certifi/2024.2.2
+PackageDownloadLocation: https://pypi.org/project/certifi/2024.6.2
FilesAnalyzed: false
PackageLicenseDeclared: MPL-2.0
PackageLicenseConcluded: MPL-2.0
PackageCopyrightText: NOASSERTION
PackageSummary: Python package for providing Mozilla's CA Bundle.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.2.2
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.6.2
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*
#####
PackageName: charset-normalizer
@@ -971,6 +967,7 @@ PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Georg Brandl (georg@python.org)
PackageDownloadLocation: https://pypi.org/project/Pygments/2.18.0
FilesAnalyzed: false
+PackageChecksum: SHA1: d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb
PackageLicenseDeclared: BSD-2-Clause
PackageLicenseConcluded: BSD-2-Clause
PackageCopyrightText: NOASSERTION
diff --git a/sbom/cve-bin-tool-py3.8.json b/sbom/cve-bin-tool-py3.8.json
index ae3a5baa9e..0e78ff1b1d 100644
--- a/sbom/cve-bin-tool-py3.8.json
+++ b/sbom/cve-bin-tool-py3.8.json
@@ -2,10 +2,10 @@
"$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.6",
- "serialNumber": "urn:uuid:f53f9e27-e6db-4127-9e63-6435bf1f921e",
+ "serialNumber": "urn:uuid:98b04938-ce5b-4df5-9d99-2eacbcb84cc3",
"version": 1,
"metadata": {
- "timestamp": "2024-05-20T00:29:17Z",
+ "timestamp": "2024-06-17T00:30:29Z",
"tools": {
"components": [
{
@@ -658,7 +658,7 @@
"type": "library",
"bom-ref": "16-gsutil",
"name": "gsutil",
- "version": "5.29",
+ "version": "5.30",
"supplier": {
"name": "Google Inc .",
"contact": [
@@ -667,7 +667,7 @@
}
]
},
- "cpe": "cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*",
"description": "A command line tool for interacting with cloud storage services.",
"licenses": [
{
@@ -679,12 +679,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/gsutil/5.29",
+ "url": "https://pypi.org/project/gsutil/5.30",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/gsutil@5.29",
+ "purl": "pkg:pypi/gsutil@5.30",
"properties": [
{
"name": "language",
@@ -700,7 +700,7 @@
"type": "library",
"bom-ref": "17-argcomplete",
"name": "argcomplete",
- "version": "3.3.0",
+ "version": "3.4.0",
"supplier": {
"name": "Andrey Kislyuk",
"contact": [
@@ -709,14 +709,8 @@
}
]
},
- "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*",
"description": "Bash tab completion for argparse",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "c7cc834df1fddcf94bd35b740fef7c7ab8e9c350"
- }
- ],
"licenses": [
{
"license": {
@@ -727,12 +721,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/argcomplete/3.3.0",
+ "url": "https://pypi.org/project/argcomplete/3.4.0",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/argcomplete@3.3.0",
+ "purl": "pkg:pypi/argcomplete@3.4.0",
"properties": [
{
"name": "language",
@@ -1520,7 +1514,7 @@
"type": "library",
"bom-ref": "35-cryptography",
"name": "cryptography",
- "version": "42.0.7",
+ "version": "42.0.8",
"supplier": {
"name": "The Python Cryptographic Authority and individual contributors",
"contact": [
@@ -1529,7 +1523,7 @@
}
]
},
- "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*",
"description": "cryptography is a package which provides cryptographic recipes and primitives to Python developers.",
"licenses": [
{
@@ -1538,12 +1532,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/cryptography/42.0.7",
+ "url": "https://pypi.org/project/cryptography/42.0.8",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/cryptography@42.0.7",
+ "purl": "pkg:pypi/cryptography@42.0.8",
"properties": [
{
"name": "language",
@@ -1839,7 +1833,7 @@
"type": "library",
"bom-ref": "42-zipp",
"name": "zipp",
- "version": "3.18.2",
+ "version": "3.19.2",
"supplier": {
"name": "Jason R .",
"contact": [
@@ -1848,22 +1842,16 @@
}
]
},
- "cpe": "cpe:2.3:a:jason_r.:zipp:3.18.2:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:jason_r.:zipp:3.19.2:*:*:*:*:*:*:*",
"description": "Backport of pathlib-compatible object wrapper for zip files",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "051250eb0e3024d75e7de09921e4efab074f0112"
- }
- ],
"externalReferences": [
{
- "url": "https://pypi.org/project/zipp/3.18.2",
+ "url": "https://pypi.org/project/zipp/3.19.2",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/zipp@3.18.2",
+ "purl": "pkg:pypi/zipp@3.19.2",
"properties": [
{
"name": "language",
@@ -2307,18 +2295,12 @@
"type": "library",
"bom-ref": "54-packageurl-python",
"name": "packageurl-python",
- "version": "0.15.0",
+ "version": "0.15.1",
"supplier": {
"name": "the purl authors"
},
- "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*",
"description": "A purl aka. Package URL parser and builder",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "a46d42493bbb7ae1a227be7bbd6b180a149ad3b1"
- }
- ],
"licenses": [
{
"license": {
@@ -2329,12 +2311,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/packageurl-python/0.15.0",
+ "url": "https://pypi.org/project/packageurl-python/0.15.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packageurl-python@0.15.0",
+ "purl": "pkg:pypi/packageurl-python@0.15.1",
"properties": [
{
"name": "language",
@@ -2350,7 +2332,7 @@
"type": "library",
"bom-ref": "55-packaging",
"name": "packaging",
- "version": "24.0",
+ "version": "24.1",
"supplier": {
"name": "Donald Stufft",
"contact": [
@@ -2359,16 +2341,16 @@
}
]
},
- "cpe": "cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*",
"description": "Core utilities for Python packages",
"externalReferences": [
{
- "url": "https://pypi.org/project/packaging/24.0",
+ "url": "https://pypi.org/project/packaging/24.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packaging@24.0",
+ "purl": "pkg:pypi/packaging@24.1",
"properties": [
{
"name": "language",
@@ -2516,7 +2498,7 @@
"type": "library",
"bom-ref": "59-requests",
"name": "requests",
- "version": "2.31.0",
+ "version": "2.32.3",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2525,14 +2507,8 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*",
"description": "Python HTTP for Humans.",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4"
- }
- ],
"licenses": [
{
"license": {
@@ -2543,12 +2519,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/requests/2.31.0",
+ "url": "https://pypi.org/project/requests/2.32.3",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/requests@2.31.0",
+ "purl": "pkg:pypi/requests@2.32.3",
"properties": [
{
"name": "language",
@@ -2564,7 +2540,7 @@
"type": "library",
"bom-ref": "60-certifi",
"name": "certifi",
- "version": "2024.2.2",
+ "version": "2024.6.2",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2573,7 +2549,7 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*",
"description": "Python package for providing Mozilla's CA Bundle.",
"licenses": [
{
@@ -2585,12 +2561,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/certifi/2024.2.2",
+ "url": "https://pypi.org/project/certifi/2024.6.2",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/certifi@2024.2.2",
+ "purl": "pkg:pypi/certifi@2024.6.2",
"properties": [
{
"name": "language",
@@ -2821,6 +2797,12 @@
},
"cpe": "cpe:2.3:a:georg_brandl:pygments:2.18.0:*:*:*:*:*:*:*",
"description": "Pygments is a syntax highlighting package written in Python.",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb"
+ }
+ ],
"licenses": [
{
"license": {
@@ -2852,7 +2834,7 @@
"type": "library",
"bom-ref": "67-typing-extensions",
"name": "typing-extensions",
- "version": "4.11.0",
+ "version": "4.12.2",
"supplier": {
"name": "Guido van Jukka ukasz Michael",
"contact": [
@@ -2861,22 +2843,16 @@
}
]
},
- "cpe": "cpe:2.3:a:guido_van_jukka_ukasz_michael:typing-extensions:4.11.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:guido_van_jukka_ukasz_michael:typing-extensions:4.12.2:*:*:*:*:*:*:*",
"description": "Backported and Experimental Type Hints for Python 3.8+",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "d4d929d44bd984350e2d17726362295f588eaace"
- }
- ],
"externalReferences": [
{
- "url": "https://pypi.org/project/typing_extensions/4.11.0",
+ "url": "https://pypi.org/project/typing_extensions/4.12.2",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/typing-extensions@4.11.0",
+ "purl": "pkg:pypi/typing-extensions@4.12.2",
"properties": [
{
"name": "language",
diff --git a/sbom/cve-bin-tool-py3.8.spdx b/sbom/cve-bin-tool-py3.8.spdx
index e729f4f788..b216c8945a 100644
--- a/sbom/cve-bin-tool-py3.8.spdx
+++ b/sbom/cve-bin-tool-py3.8.spdx
@@ -2,10 +2,10 @@ SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: Python-cve-bin-tool
-DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-21bd54f8-a7dd-4a2c-8575-f6ff48205e56
+DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-9b2572c3-bc89-4031-9f9c-0823282d441e
LicenseListVersion: 3.22
Creator: Tool: sbom4python-0.10.4
-Created: 2024-05-20T00:27:33Z
+Created: 2024-06-17T00:28:55Z
CreatorComment: This document has been automatically generated.
#####
@@ -250,35 +250,34 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:tomas_aparicio:filetype:1.2.0:*:*:*:*:
PackageName: gsutil
SPDXID: SPDXRef-Package-16-gsutil
-PackageVersion: 5.29
+PackageVersion: 5.30
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Google Inc. (buganizer-system+187143@google.com)
-PackageDownloadLocation: https://pypi.org/project/gsutil/5.29
+PackageDownloadLocation: https://pypi.org/project/gsutil/5.30
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: gsutil declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: A command line tool for interacting with cloud storage services.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.29
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.30
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*
#####
PackageName: argcomplete
SPDXID: SPDXRef-Package-17-argcomplete
-PackageVersion: 3.3.0
+PackageVersion: 3.4.0
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Andrey Kislyuk (kislyuk@gmail.com)
-PackageDownloadLocation: https://pypi.org/project/argcomplete/3.3.0
+PackageDownloadLocation: https://pypi.org/project/argcomplete/3.4.0
FilesAnalyzed: false
-PackageChecksum: SHA1: c7cc834df1fddcf94bd35b740fef7c7ab8e9c350
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: argcomplete declares Apache Software License which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Bash tab completion for argparse
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.3.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.4.0
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*
#####
PackageName: crcmod
@@ -558,17 +557,17 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_pyopenssl_developers:pyopenssl:24.
PackageName: cryptography
SPDXID: SPDXRef-Package-35-cryptography
-PackageVersion: 42.0.7
+PackageVersion: 42.0.8
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Organization: The Python Cryptographic Authority and individual contributors (cryptography-dev@python.org)
-PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.7
+PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.8
FilesAnalyzed: false
PackageLicenseDeclared: Apache-2.0 OR BSD-3-Clause
PackageLicenseConcluded: Apache-2.0 OR BSD-3-Clause
PackageCopyrightText: NOASSERTION
PackageSummary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.7
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.8
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*
#####
PackageName: cffi
@@ -671,18 +670,17 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:jason_r._coombs:importlib-metadata:7.1
PackageName: zipp
SPDXID: SPDXRef-Package-42-zipp
-PackageVersion: 3.18.2
+PackageVersion: 3.19.2
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Organization: Jason R. (jaraco@jaraco.com)
-PackageDownloadLocation: https://pypi.org/project/zipp/3.18.2
+PackageDownloadLocation: https://pypi.org/project/zipp/3.19.2
FilesAnalyzed: false
-PackageChecksum: SHA1: 051250eb0e3024d75e7de09921e4efab074f0112
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageSummary: Backport of pathlib-compatible object wrapper for zip files
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/zipp@3.18.2
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:jason_r.:zipp:3.18.2:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/zipp@3.19.2
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:jason_r.:zipp:3.19.2:*:*:*:*:*:*:*
#####
PackageName: importlib-resources
@@ -857,33 +855,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:raphael_barrois:semantic-version:2.10.
PackageName: packageurl-python
SPDXID: SPDXRef-Package-54-packageurl-python
-PackageVersion: 0.15.0
+PackageVersion: 0.15.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: the purl authors
-PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.0
+PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.1
FilesAnalyzed: false
-PackageChecksum: SHA1: a46d42493bbb7ae1a227be7bbd6b180a149ad3b1
PackageLicenseDeclared: MIT
PackageLicenseConcluded: MIT
PackageCopyrightText: NOASSERTION
PackageSummary: A purl aka. Package URL parser and builder
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*
#####
PackageName: packaging
SPDXID: SPDXRef-Package-55-packaging
-PackageVersion: 24.0
+PackageVersion: 24.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Donald Stufft (donald@stufft.io)
-PackageDownloadLocation: https://pypi.org/project/packaging/24.0
+PackageDownloadLocation: https://pypi.org/project/packaging/24.1
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageSummary: Core utilities for Python packages
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*
#####
PackageName: plotly
@@ -936,34 +933,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:vinay_sajip:python-gnupg:0.5.2:*:*:*:*
PackageName: requests
SPDXID: SPDXRef-Package-59-requests
-PackageVersion: 2.31.0
+PackageVersion: 2.32.3
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.org)
-PackageDownloadLocation: https://pypi.org/project/requests/2.31.0
+PackageDownloadLocation: https://pypi.org/project/requests/2.32.3
FilesAnalyzed: false
-PackageChecksum: SHA1: 147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4
-PackageLicenseDeclared: NOASSERTION
+PackageLicenseDeclared: Apache-2.0
PackageLicenseConcluded: Apache-2.0
-PackageLicenseComments: requests declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Python HTTP for Humans.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.31.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.32.3
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*
#####
PackageName: certifi
SPDXID: SPDXRef-Package-60-certifi
-PackageVersion: 2024.2.2
+PackageVersion: 2024.6.2
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.com)
-PackageDownloadLocation: https://pypi.org/project/certifi/2024.2.2
+PackageDownloadLocation: https://pypi.org/project/certifi/2024.6.2
FilesAnalyzed: false
PackageLicenseDeclared: MPL-2.0
PackageLicenseConcluded: MPL-2.0
PackageCopyrightText: NOASSERTION
PackageSummary: Python package for providing Mozilla's CA Bundle.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.2.2
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.6.2
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*
#####
PackageName: charset-normalizer
@@ -1051,6 +1046,7 @@ PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Georg Brandl (georg@python.org)
PackageDownloadLocation: https://pypi.org/project/Pygments/2.18.0
FilesAnalyzed: false
+PackageChecksum: SHA1: d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb
PackageLicenseDeclared: BSD-2-Clause
PackageLicenseConcluded: BSD-2-Clause
PackageCopyrightText: NOASSERTION
@@ -1061,18 +1057,17 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:georg_brandl:pygments:2.18.0:*:*:*:*:*
PackageName: typing-extensions
SPDXID: SPDXRef-Package-67-typing-extensions
-PackageVersion: 4.11.0
+PackageVersion: 4.12.2
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Organization: Guido van Jukka ukasz Michael (levkivskyi@gmail.com)
-PackageDownloadLocation: https://pypi.org/project/typing_extensions/4.11.0
+PackageDownloadLocation: https://pypi.org/project/typing_extensions/4.12.2
FilesAnalyzed: false
-PackageChecksum: SHA1: d4d929d44bd984350e2d17726362295f588eaace
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageSummary: Backported and Experimental Type Hints for Python 3.8+
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/typing-extensions@4.11.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:guido_van_jukka_ukasz_michael:typing-extensions:4.11.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/typing-extensions@4.12.2
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:guido_van_jukka_ukasz_michael:typing-extensions:4.12.2:*:*:*:*:*:*:*
#####
PackageName: rpmfile
diff --git a/sbom/cve-bin-tool-py3.9.json b/sbom/cve-bin-tool-py3.9.json
index 305e8c864d..7a04ba8fd0 100644
--- a/sbom/cve-bin-tool-py3.9.json
+++ b/sbom/cve-bin-tool-py3.9.json
@@ -2,10 +2,10 @@
"$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.6",
- "serialNumber": "urn:uuid:da25ffa1-1384-461d-a6c5-84dfce937e55",
+ "serialNumber": "urn:uuid:7ce38d53-46f3-4649-80ba-ffe493f3fa89",
"version": 1,
"metadata": {
- "timestamp": "2024-05-20T00:28:52Z",
+ "timestamp": "2024-06-17T00:30:00Z",
"tools": {
"components": [
{
@@ -658,7 +658,7 @@
"type": "library",
"bom-ref": "16-gsutil",
"name": "gsutil",
- "version": "5.29",
+ "version": "5.30",
"supplier": {
"name": "Google Inc .",
"contact": [
@@ -667,7 +667,7 @@
}
]
},
- "cpe": "cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*",
"description": "A command line tool for interacting with cloud storage services.",
"licenses": [
{
@@ -679,12 +679,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/gsutil/5.29",
+ "url": "https://pypi.org/project/gsutil/5.30",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/gsutil@5.29",
+ "purl": "pkg:pypi/gsutil@5.30",
"properties": [
{
"name": "language",
@@ -700,7 +700,7 @@
"type": "library",
"bom-ref": "17-argcomplete",
"name": "argcomplete",
- "version": "3.3.0",
+ "version": "3.4.0",
"supplier": {
"name": "Andrey Kislyuk",
"contact": [
@@ -709,14 +709,8 @@
}
]
},
- "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*",
"description": "Bash tab completion for argparse",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "c7cc834df1fddcf94bd35b740fef7c7ab8e9c350"
- }
- ],
"licenses": [
{
"license": {
@@ -727,12 +721,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/argcomplete/3.3.0",
+ "url": "https://pypi.org/project/argcomplete/3.4.0",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/argcomplete@3.3.0",
+ "purl": "pkg:pypi/argcomplete@3.4.0",
"properties": [
{
"name": "language",
@@ -1520,7 +1514,7 @@
"type": "library",
"bom-ref": "35-cryptography",
"name": "cryptography",
- "version": "42.0.7",
+ "version": "42.0.8",
"supplier": {
"name": "The Python Cryptographic Authority and individual contributors",
"contact": [
@@ -1529,7 +1523,7 @@
}
]
},
- "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*",
"description": "cryptography is a package which provides cryptographic recipes and primitives to Python developers.",
"licenses": [
{
@@ -1538,12 +1532,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/cryptography/42.0.7",
+ "url": "https://pypi.org/project/cryptography/42.0.8",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/cryptography@42.0.7",
+ "purl": "pkg:pypi/cryptography@42.0.8",
"properties": [
{
"name": "language",
@@ -1839,7 +1833,7 @@
"type": "library",
"bom-ref": "42-zipp",
"name": "zipp",
- "version": "3.18.2",
+ "version": "3.19.2",
"supplier": {
"name": "Jason R .",
"contact": [
@@ -1848,22 +1842,16 @@
}
]
},
- "cpe": "cpe:2.3:a:jason_r.:zipp:3.18.2:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:jason_r.:zipp:3.19.2:*:*:*:*:*:*:*",
"description": "Backport of pathlib-compatible object wrapper for zip files",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "051250eb0e3024d75e7de09921e4efab074f0112"
- }
- ],
"externalReferences": [
{
- "url": "https://pypi.org/project/zipp/3.18.2",
+ "url": "https://pypi.org/project/zipp/3.19.2",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/zipp@3.18.2",
+ "purl": "pkg:pypi/zipp@3.19.2",
"properties": [
{
"name": "language",
@@ -2233,18 +2221,12 @@
"type": "library",
"bom-ref": "52-packageurl-python",
"name": "packageurl-python",
- "version": "0.15.0",
+ "version": "0.15.1",
"supplier": {
"name": "the purl authors"
},
- "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*",
"description": "A purl aka. Package URL parser and builder",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "a46d42493bbb7ae1a227be7bbd6b180a149ad3b1"
- }
- ],
"licenses": [
{
"license": {
@@ -2255,12 +2237,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/packageurl-python/0.15.0",
+ "url": "https://pypi.org/project/packageurl-python/0.15.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packageurl-python@0.15.0",
+ "purl": "pkg:pypi/packageurl-python@0.15.1",
"properties": [
{
"name": "language",
@@ -2276,7 +2258,7 @@
"type": "library",
"bom-ref": "53-packaging",
"name": "packaging",
- "version": "24.0",
+ "version": "24.1",
"supplier": {
"name": "Donald Stufft",
"contact": [
@@ -2285,16 +2267,16 @@
}
]
},
- "cpe": "cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*",
"description": "Core utilities for Python packages",
"externalReferences": [
{
- "url": "https://pypi.org/project/packaging/24.0",
+ "url": "https://pypi.org/project/packaging/24.1",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/packaging@24.0",
+ "purl": "pkg:pypi/packaging@24.1",
"properties": [
{
"name": "language",
@@ -2442,7 +2424,7 @@
"type": "library",
"bom-ref": "57-requests",
"name": "requests",
- "version": "2.31.0",
+ "version": "2.32.3",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2451,14 +2433,8 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*",
"description": "Python HTTP for Humans.",
- "hashes": [
- {
- "alg": "SHA-1",
- "content": "147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4"
- }
- ],
"licenses": [
{
"license": {
@@ -2469,12 +2445,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/requests/2.31.0",
+ "url": "https://pypi.org/project/requests/2.32.3",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/requests@2.31.0",
+ "purl": "pkg:pypi/requests@2.32.3",
"properties": [
{
"name": "language",
@@ -2490,7 +2466,7 @@
"type": "library",
"bom-ref": "58-certifi",
"name": "certifi",
- "version": "2024.2.2",
+ "version": "2024.6.2",
"supplier": {
"name": "Kenneth Reitz",
"contact": [
@@ -2499,7 +2475,7 @@
}
]
},
- "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*",
+ "cpe": "cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*",
"description": "Python package for providing Mozilla's CA Bundle.",
"licenses": [
{
@@ -2511,12 +2487,12 @@
],
"externalReferences": [
{
- "url": "https://pypi.org/project/certifi/2024.2.2",
+ "url": "https://pypi.org/project/certifi/2024.6.2",
"type": "distribution",
"comment": "Download location for component"
}
],
- "purl": "pkg:pypi/certifi@2024.2.2",
+ "purl": "pkg:pypi/certifi@2024.6.2",
"properties": [
{
"name": "language",
@@ -2747,6 +2723,12 @@
},
"cpe": "cpe:2.3:a:georg_brandl:pygments:2.18.0:*:*:*:*:*:*:*",
"description": "Pygments is a syntax highlighting package written in Python.",
+ "hashes": [
+ {
+ "alg": "SHA-1",
+ "content": "d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb"
+ }
+ ],
"licenses": [
{
"license": {
diff --git a/sbom/cve-bin-tool-py3.9.spdx b/sbom/cve-bin-tool-py3.9.spdx
index 51f4d38c58..26ec32275f 100644
--- a/sbom/cve-bin-tool-py3.9.spdx
+++ b/sbom/cve-bin-tool-py3.9.spdx
@@ -2,10 +2,10 @@ SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: Python-cve-bin-tool
-DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-3138d3f8-dc63-447a-b0be-cca4b60da110
+DocumentNamespace: http://spdx.org/spdxdocs/Python-cve-bin-tool-c423bff7-bd23-4269-8ccb-fd27c143119f
LicenseListVersion: 3.22
Creator: Tool: sbom4python-0.10.4
-Created: 2024-05-20T00:27:19Z
+Created: 2024-06-17T00:28:35Z
CreatorComment: This document has been automatically generated.
#####
@@ -250,35 +250,34 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:tomas_aparicio:filetype:1.2.0:*:*:*:*:
PackageName: gsutil
SPDXID: SPDXRef-Package-16-gsutil
-PackageVersion: 5.29
+PackageVersion: 5.30
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Google Inc. (buganizer-system+187143@google.com)
-PackageDownloadLocation: https://pypi.org/project/gsutil/5.29
+PackageDownloadLocation: https://pypi.org/project/gsutil/5.30
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: gsutil declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: A command line tool for interacting with cloud storage services.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.29
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.29:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/gsutil@5.30
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:google_inc.:gsutil:5.30:*:*:*:*:*:*:*
#####
PackageName: argcomplete
SPDXID: SPDXRef-Package-17-argcomplete
-PackageVersion: 3.3.0
+PackageVersion: 3.4.0
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Andrey Kislyuk (kislyuk@gmail.com)
-PackageDownloadLocation: https://pypi.org/project/argcomplete/3.3.0
+PackageDownloadLocation: https://pypi.org/project/argcomplete/3.4.0
FilesAnalyzed: false
-PackageChecksum: SHA1: c7cc834df1fddcf94bd35b740fef7c7ab8e9c350
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: Apache-2.0
PackageLicenseComments: argcomplete declares Apache Software License which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Bash tab completion for argparse
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.3.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.3.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/argcomplete@3.4.0
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:andrey_kislyuk:argcomplete:3.4.0:*:*:*:*:*:*:*
#####
PackageName: crcmod
@@ -558,17 +557,17 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_pyopenssl_developers:pyopenssl:24.
PackageName: cryptography
SPDXID: SPDXRef-Package-35-cryptography
-PackageVersion: 42.0.7
+PackageVersion: 42.0.8
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Organization: The Python Cryptographic Authority and individual contributors (cryptography-dev@python.org)
-PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.7
+PackageDownloadLocation: https://pypi.org/project/cryptography/42.0.8
FilesAnalyzed: false
PackageLicenseDeclared: Apache-2.0 OR BSD-3-Clause
PackageLicenseConcluded: Apache-2.0 OR BSD-3-Clause
PackageCopyrightText: NOASSERTION
PackageSummary: cryptography is a package which provides cryptographic recipes and primitives to Python developers.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.7
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.7:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/cryptography@42.0.8
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_python_cryptographic_authority_and_individual_contributors:cryptography:42.0.8:*:*:*:*:*:*:*
#####
PackageName: cffi
@@ -671,18 +670,17 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:jason_r._coombs:importlib-metadata:7.1
PackageName: zipp
SPDXID: SPDXRef-Package-42-zipp
-PackageVersion: 3.18.2
+PackageVersion: 3.19.2
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Organization: Jason R. (jaraco@jaraco.com)
-PackageDownloadLocation: https://pypi.org/project/zipp/3.18.2
+PackageDownloadLocation: https://pypi.org/project/zipp/3.19.2
FilesAnalyzed: false
-PackageChecksum: SHA1: 051250eb0e3024d75e7de09921e4efab074f0112
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageSummary: Backport of pathlib-compatible object wrapper for zip files
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/zipp@3.18.2
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:jason_r.:zipp:3.18.2:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/zipp@3.19.2
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:jason_r.:zipp:3.19.2:*:*:*:*:*:*:*
#####
PackageName: jinja2
@@ -826,33 +824,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:raphael_barrois:semantic-version:2.10.
PackageName: packageurl-python
SPDXID: SPDXRef-Package-52-packageurl-python
-PackageVersion: 0.15.0
+PackageVersion: 0.15.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: the purl authors
-PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.0
+PackageDownloadLocation: https://pypi.org/project/packageurl-python/0.15.1
FilesAnalyzed: false
-PackageChecksum: SHA1: a46d42493bbb7ae1a227be7bbd6b180a149ad3b1
PackageLicenseDeclared: MIT
PackageLicenseConcluded: MIT
PackageCopyrightText: NOASSERTION
PackageSummary: A purl aka. Package URL parser and builder
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packageurl-python@0.15.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:the_purl_authors:packageurl-python:0.15.1:*:*:*:*:*:*:*
#####
PackageName: packaging
SPDXID: SPDXRef-Package-53-packaging
-PackageVersion: 24.0
+PackageVersion: 24.1
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Donald Stufft (donald@stufft.io)
-PackageDownloadLocation: https://pypi.org/project/packaging/24.0
+PackageDownloadLocation: https://pypi.org/project/packaging/24.1
FilesAnalyzed: false
PackageLicenseDeclared: NOASSERTION
PackageLicenseConcluded: NOASSERTION
PackageCopyrightText: NOASSERTION
PackageSummary: Core utilities for Python packages
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/packaging@24.1
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:donald_stufft:packaging:24.1:*:*:*:*:*:*:*
#####
PackageName: plotly
@@ -905,34 +902,32 @@ ExternalRef: SECURITY cpe23Type cpe:2.3:a:vinay_sajip:python-gnupg:0.5.2:*:*:*:*
PackageName: requests
SPDXID: SPDXRef-Package-57-requests
-PackageVersion: 2.31.0
+PackageVersion: 2.32.3
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.org)
-PackageDownloadLocation: https://pypi.org/project/requests/2.31.0
+PackageDownloadLocation: https://pypi.org/project/requests/2.32.3
FilesAnalyzed: false
-PackageChecksum: SHA1: 147c8511ddbfa5e8f71bbf5c18ede0c4ceb3bba4
-PackageLicenseDeclared: NOASSERTION
+PackageLicenseDeclared: Apache-2.0
PackageLicenseConcluded: Apache-2.0
-PackageLicenseComments: requests declares Apache 2.0 which is not currently a valid SPDX License identifier or expression.
PackageCopyrightText: NOASSERTION
PackageSummary: Python HTTP for Humans.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.31.0
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.31.0:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/requests@2.32.3
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:requests:2.32.3:*:*:*:*:*:*:*
#####
PackageName: certifi
SPDXID: SPDXRef-Package-58-certifi
-PackageVersion: 2024.2.2
+PackageVersion: 2024.6.2
PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Kenneth Reitz (me@kennethreitz.com)
-PackageDownloadLocation: https://pypi.org/project/certifi/2024.2.2
+PackageDownloadLocation: https://pypi.org/project/certifi/2024.6.2
FilesAnalyzed: false
PackageLicenseDeclared: MPL-2.0
PackageLicenseConcluded: MPL-2.0
PackageCopyrightText: NOASSERTION
PackageSummary: Python package for providing Mozilla's CA Bundle.
-ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.2.2
-ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.2.2:*:*:*:*:*:*:*
+ExternalRef: PACKAGE_MANAGER purl pkg:pypi/certifi@2024.6.2
+ExternalRef: SECURITY cpe23Type cpe:2.3:a:kenneth_reitz:certifi:2024.6.2:*:*:*:*:*:*:*
#####
PackageName: charset-normalizer
@@ -1020,6 +1015,7 @@ PrimaryPackagePurpose: LIBRARY
PackageSupplier: Person: Georg Brandl (georg@python.org)
PackageDownloadLocation: https://pypi.org/project/Pygments/2.18.0
FilesAnalyzed: false
+PackageChecksum: SHA1: d7d11f6e6d3aa97805215c1cc833ea5f0ef1fcbb
PackageLicenseDeclared: BSD-2-Clause
PackageLicenseConcluded: BSD-2-Clause
PackageCopyrightText: NOASSERTION
diff --git a/setup.py b/setup.py
index 5f0ba969c6..979618656c 100644
--- a/setup.py
+++ b/setup.py
@@ -3,9 +3,13 @@
import ast
import os
+import pathlib
+import re
from setuptools import find_packages, setup
+PACKAGE_ROOT_PATH = pathlib.Path(__file__).parent.resolve()
+
with open("README.md", encoding="utf-8") as f:
readme = f.read()
@@ -18,6 +22,30 @@
VERSION = ast.literal_eval(line.strip().split("=")[-1].strip())
break
+
+def enumerate_entry_points_parsers():
+ """Reads the files in cve_bin_tool/parsers/to auto determine list"""
+ parsers = {}
+ for path in PACKAGE_ROOT_PATH.joinpath(
+ "cve_bin_tool",
+ "parsers",
+ ).glob("*.py"):
+ if "__init__" == path.stem:
+ continue
+ contents = path.read_text()
+ for re_match in re.finditer(r"^class (\w+)", contents, re.MULTILINE):
+ parser_cls_name = re_match[1]
+ parsers[".".join([path.stem, parser_cls_name])] = ":".join(
+ [
+ str(path.relative_to(PACKAGE_ROOT_PATH).with_suffix("")).replace(
+ os.path.sep, "."
+ ),
+ parser_cls_name,
+ ],
+ )
+ return parsers
+
+
setup_kwargs = dict(
name="cve-bin-tool",
version=VERSION,
@@ -89,7 +117,18 @@
)
if filename.endswith(".py") and "__init__" not in filename
],
+ "cve_bin_tool.parsers": [
+ "{} = {}".format(
+ parser_entry_point_name,
+ entry_point_path,
+ )
+ for (
+ parser_entry_point_name,
+ entry_point_path,
+ ) in enumerate_entry_points_parsers().items()
+ ],
},
)
-setup(**setup_kwargs)
+if __name__ == "__main__":
+ setup(**setup_kwargs)
diff --git a/test/language_data/fail_pom.xml b/test/language_data/fail_pom.xml
index 42ff70065a..e6b7c4387f 100644
--- a/test/language_data/fail_pom.xml
+++ b/test/language_data/fail_pom.xml
@@ -22,7 +22,6 @@
5.8.2
4.2.0
UTF-8
- 2.0.0-alpha5
@@ -80,18 +79,6 @@
${mockito.version}
test
-
- org.slf4j
- slf4j-api
- ${slf4j.version}
- test
-
-
- org.slf4j
- slf4j-simple
- ${slf4j.version}
- test
-
diff --git a/test/parser_env_test_0001.env b/test/parser_env_test_0001.env
new file mode 100644
index 0000000000..5935efa108
--- /dev/null
+++ b/test/parser_env_test_0001.env
@@ -0,0 +1,4 @@
+CVE_BIN_TOOL_0_PRODUCT="myproduct"
+CVE_BIN_TOOL_0_VENDOR="myvendor"
+CVE_BIN_TOOL_0_VERSION="v0.0.0.dev-15abff2d529396937e18c657ecee1ed224842000"
+CVE_BIN_TOOL_0_AD_HOC_CVE_ID="CVE-0001-15004435-aa84-43ff-9c26-f703a26069f8"
diff --git a/test/test_cli.py b/test/test_cli.py
index c60e514b1b..6c62e33668 100644
--- a/test/test_cli.py
+++ b/test/test_cli.py
@@ -809,3 +809,32 @@ def test_config_generator(self, args, expected_files, expected_contents, caplog)
assert expected_content in content
# Cleanup
os.remove(expected_files)
+
+ def test_disabled_sources(self, caplog):
+ """Attempts to disable various data sources and makes sure they appear
+ to be disabled correctly.
+
+ This only tests for disabled messages, it doesn't check on the update code
+ because we'd have to actually do updates then and they're slow.
+ """
+
+ # attempt to call with all sources disabled
+ with caplog.at_level(logging.INFO):
+ main(
+ [
+ "cve-bin-tool",
+ "--update",
+ "never",
+ "--nvd-api-key",
+ "no",
+ "-n",
+ "json-mirror",
+ "--disable-data-source",
+ "CURL,EPSS,GAD,OSV,REDHAT,RSD",
+ self.tempdir,
+ ]
+ )
+ # check that nvd key was disabled as expected
+ assert "NVD API Key was set to 'no' and will not be used" in caplog.text
+ for source in ["CURL", "EPSS", "GAD", "OSV", "REDHAT", "RSD"]:
+ assert f"Disabling data source {source}" in caplog.text
diff --git a/test/test_language_scanner.py b/test/test_language_scanner.py
index d30dfb325e..c93f80cba7 100644
--- a/test/test_language_scanner.py
+++ b/test/test_language_scanner.py
@@ -169,7 +169,12 @@ def setup_class(cls):
@pytest.mark.parametrize(
"filename, product_list",
- (((str(TEST_FILE_PATH / "pom.xml")), ["jmeter", "hamcrest"]),),
+ (
+ (
+ (str(TEST_FILE_PATH / "pom.xml")),
+ ["jmeter", "hamcrest", "slf4j-simple", "slf4j-api"],
+ ),
+ ),
)
def test_java_package(self, filename: str, product_list: set[str]) -> None:
"""Test against a valid pom.xml file for Java packages"""
@@ -252,7 +257,7 @@ def test_python_package(self, filename: str) -> None:
for product in scanner.scan_file(filename):
if product:
product_info, file_path = product
- assert product_info == ProductInfo(
- "facebook", "zstandard", "0.18.0", "/usr/local/bin/product"
- )
+ assert product_info == ProductInfo(
+ "facebook", "zstandard", "0.18.0", filename
+ )
assert file_path == filename
diff --git a/test/test_output_engine.py b/test/test_output_engine.py
index b294153d0f..a0292458d2 100644
--- a/test/test_output_engine.py
+++ b/test/test_output_engine.py
@@ -12,6 +12,7 @@
import unittest
from datetime import datetime
from pathlib import Path
+from unittest.mock import MagicMock, call, patch
from jsonschema import validate
from rich.console import Console
@@ -1124,6 +1125,20 @@ class TestOutputEngine(unittest.TestCase):
]
def setUp(self) -> None:
+ self.all_product_data = [
+ ProductInfo(
+ product="product1",
+ version="1.0",
+ vendor="VendorA",
+ location="/usr/local/bin/product",
+ ),
+ ProductInfo(
+ product="product2",
+ version="2.0",
+ vendor="unknown",
+ location="/usr/local/bin/product",
+ ),
+ ]
self.output_engine = OutputEngine(
all_cve_data=self.MOCK_OUTPUT,
scanned_dir="",
@@ -1134,6 +1149,68 @@ def setUp(self) -> None:
)
self.mock_file = tempfile.NamedTemporaryFile("w+", encoding="utf-8")
+ def test_generate_sbom(self):
+ with patch(
+ "cve_bin_tool.output_engine.SBOMPackage"
+ ) as mock_sbom_package, patch("cve_bin_tool.output_engine.SBOMRelationship"):
+ mock_package_instance = MagicMock()
+ mock_sbom_package.return_value = mock_package_instance
+
+ self.output_engine.generate_sbom(
+ all_product_data=self.all_product_data,
+ filename="test.sbom",
+ sbom_type="spdx",
+ sbom_format="tag",
+ sbom_root="CVE-SCAN",
+ )
+
+ # Assertions
+ mock_package_instance.set_name.assert_any_call("CVEBINTOOL-CVE-SCAN")
+
+ # Check if set_name is called for each product
+ expected_calls = [
+ call(product.product) for product in self.all_product_data
+ ]
+ mock_package_instance.set_name.assert_has_calls(
+ expected_calls, any_order=True
+ )
+
+ # Check if set_version is called for each product
+ expected_calls = [
+ call(product.version) for product in self.all_product_data
+ ]
+ mock_package_instance.set_version.assert_has_calls(
+ expected_calls, any_order=True
+ )
+
+ # Check if set_supplier is called for VendorA
+ mock_package_instance.set_supplier.assert_any_call(
+ "Organization", "VendorA"
+ )
+
+ for call_args in mock_package_instance.set_supplier.call_args_list:
+ args, _ = call_args
+ self.assertNotEqual(args, ("Organization", "unknown"))
+
+ # Check if set_licensedeclared and set_licenseconcluded are called for each product
+ expected_calls = [call("NOASSERTION")] * len(self.all_product_data)
+ mock_package_instance.set_licensedeclared.assert_has_calls(
+ expected_calls, any_order=True
+ )
+ mock_package_instance.set_licenseconcluded.assert_has_calls(
+ expected_calls, any_order=True
+ )
+
+ # Ensure packages are added to sbom_packages correctly
+ expected_packages = {
+ mock_package_instance.get_package.return_value,
+ mock_package_instance.get_package.return_value,
+ }
+ actual_packages = [
+ package for package in self.output_engine.sbom_packages.values()
+ ]
+ self.assertEqual(actual_packages, list(expected_packages))
+
def tearDown(self) -> None:
self.mock_file.close()
diff --git a/test/test_parsers.py b/test/test_parsers.py
new file mode 100644
index 0000000000..7e102e59f2
--- /dev/null
+++ b/test/test_parsers.py
@@ -0,0 +1,104 @@
+from __future__ import annotations
+
+import atexit
+import contextlib
+import pathlib
+import re
+import tempfile
+import unittest
+
+from packageurl import PackageURL
+
+from cve_bin_tool.cvedb import CVEDB
+from cve_bin_tool.log import LOGGER
+from cve_bin_tool.parsers.dart import DartParser
+from cve_bin_tool.parsers.env import EnvParser
+from cve_bin_tool.parsers.go import GoParser
+from cve_bin_tool.parsers.java import JavaParser
+from cve_bin_tool.parsers.javascript import JavascriptParser
+from cve_bin_tool.parsers.parse import valid_files as actual_valid_files
+from cve_bin_tool.parsers.perl import PerlParser
+from cve_bin_tool.parsers.php import PhpParser
+from cve_bin_tool.parsers.python import PythonParser, PythonRequirementsParser
+from cve_bin_tool.parsers.r import RParser
+from cve_bin_tool.parsers.ruby import RubyParser
+from cve_bin_tool.parsers.rust import RustParser
+from cve_bin_tool.parsers.swift import SwiftParser
+from cve_bin_tool.util import ProductInfo, ScanInfo
+
+cve_db = CVEDB()
+logger = LOGGER.getChild(__name__)
+
+stack = contextlib.ExitStack().__enter__()
+tmpdir = stack.enter_context(
+ tempfile.TemporaryDirectory(prefix="cve-bin-tool-TEST_ENV")
+)
+atexit.register(lambda: stack.__exit__(None, None, None))
+
+EXPECTED_VALID_FILES = {
+ "pom.xml": [JavaParser],
+ "package-lock.json": [JavascriptParser],
+ "Cargo.lock": [RustParser],
+ "renv.lock": [RParser],
+ "requirements.txt": [PythonRequirementsParser],
+ "go.mod": [GoParser],
+ "PKG-INFO: ": [PythonParser],
+ "METADATA: ": [PythonParser],
+ "Gemfile.lock": [RubyParser],
+ "Package.resolved": [SwiftParser],
+ "composer.lock": [PhpParser],
+ "cpanfile": [PerlParser],
+ "pubspec.lock": [DartParser],
+}
+
+PARSER_ENV_TEST_0001_ENV_CONTENTS = (
+ pathlib.Path(__file__).parent.joinpath("parser_env_test_0001.env").read_text()
+)
+
+
+class TestParsers(unittest.TestCase):
+ maxDiff = None
+
+ def test_parser_match_filenames_results_in_correct_valid_files(self):
+ for detection in EXPECTED_VALID_FILES.keys():
+ self.assertIn(
+ detection,
+ actual_valid_files,
+ "Expected registered file type {detection!r} not found in loaded file type list",
+ )
+ for plugin in EXPECTED_VALID_FILES[detection]:
+ self.assertIn(
+ plugin,
+ actual_valid_files[detection],
+ "Expected registered file type {detection!r} is missing Parser class {plugin!r}",
+ )
+
+ def test_parser_env_test_0001(self):
+ file_path = pathlib.Path(tmpdir, ".env").resolve()
+ file_path.write_text(PARSER_ENV_TEST_0001_ENV_CONTENTS)
+ env_parser = EnvParser(cve_db, logger)
+ results = list(env_parser.run_checker(file_path))
+ self.assertListEqual(
+ results,
+ [
+ ScanInfo(
+ product_info=ProductInfo(
+ vendor="myvendor",
+ product="myproduct",
+ version="v0.0.0.dev-15abff2d529396937e18c657ecee1ed224842000",
+ # TODO location?
+ location="/usr/local/bin/product",
+ # TODO purl
+ purl=PackageURL(
+ type="ad-hoc",
+ namespace="myvendor",
+ name=re.sub(r"[^a-zA-Z0-9._-]", "", "myproduct").lower(),
+ version="v0.0.0.dev-15abff2d529396937e18c657ecee1ed224842000",
+ qualifiers={},
+ subpath=None,
+ ),
+ ),
+ file_path=file_path,
+ )
+ ],
+ )
diff --git a/test/test_source_osv.py b/test/test_source_osv.py
index b1ec7fe301..9bb105b0ce 100644
--- a/test/test_source_osv.py
+++ b/test/test_source_osv.py
@@ -117,9 +117,9 @@ def teardown_class(cls):
}
format_data = {
- "CVE-2018-20133": {
+ "PYSEC-2018-103": {
"severity_data": {
- "ID": "CVE-2018-20133",
+ "ID": "PYSEC-2018-103",
"severity": "unknown",
"description": "unknown",
"score": "unknown",
@@ -129,7 +129,7 @@ def teardown_class(cls):
},
"affected_data": [
{
- "cve_id": "CVE-2018-20133",
+ "cve_id": "PYSEC-2018-103",
"vendor": "unknown",
"product": "ymlref",
"version": "*",
@@ -140,9 +140,9 @@ def teardown_class(cls):
}
],
},
- "CVE-2014-5461": {
+ "DLA-47-1": {
"severity_data": {
- "ID": "CVE-2014-5461",
+ "ID": "DLA-47-1",
"severity": "unknown",
"description": "lua5.1 - security update",
"score": "unknown",
@@ -152,7 +152,7 @@ def teardown_class(cls):
},
"affected_data": [
{
- "cve_id": "CVE-2014-5461",
+ "cve_id": "DLA-47-1",
"vendor": "unknown",
"product": "lua5.1",
"version": "*",
diff --git a/test/test_vex.py b/test/test_vex.py
new file mode 100644
index 0000000000..120c62ae69
--- /dev/null
+++ b/test/test_vex.py
@@ -0,0 +1,118 @@
+# Copyright (C) 2021 Intel Corporation
+# SPDX-License-Identifier: GPL-3.0-or-later
+import json
+import unittest
+from pathlib import Path
+
+from cve_bin_tool.util import CVE, CVEData, ProductInfo, Remarks
+from cve_bin_tool.vex_manager.generate import VEXGenerate
+
+TEST_DIR = Path(__file__).parent.resolve()
+VEX_PATH = TEST_DIR / "vex"
+
+
+class TestVexGeneration(unittest.TestCase):
+ FORMATTED_DATA = {
+ ProductInfo("vendor0", "product0", "1.0", "/usr/local/bin/product"): CVEData(
+ cves=[
+ CVE(
+ "CVE-1234-1004",
+ "CRITICAL",
+ score=4.2,
+ cvss_version=2,
+ cvss_vector="C:H",
+ data_source="NVD",
+ last_modified="01-05-2019",
+ metric={
+ "EPSS": [0.00126, "0.46387"],
+ },
+ ),
+ CVE(
+ "CVE-1234-1005",
+ "MEDIUM",
+ remarks=Remarks.NotAffected,
+ comments="Detail field populated.",
+ score=4.2,
+ cvss_version=2,
+ cvss_vector="C:H",
+ data_source="NVD",
+ last_modified="01-05-2019",
+ metric={
+ "EPSS": [0.00126, "0.46387"],
+ },
+ justification="code_not_reachable",
+ response=["will_not_fix"],
+ ),
+ ],
+ paths={""},
+ ),
+ ProductInfo("vendor0", "product0", "2.8.6", "/usr/local/bin/product"): CVEData(
+ cves=[
+ CVE(
+ "CVE-1234-1007",
+ "LOW",
+ remarks=Remarks.Mitigated,
+ comments="Data field populated.",
+ score=2.5,
+ cvss_version=3,
+ cvss_vector="CVSS3.0/C:H/I:L/A:M",
+ data_source="NVD",
+ last_modified="12-12-2020",
+ metric={
+ "EPSS": [0.03895, "0.37350"],
+ },
+ ),
+ CVE(
+ "CVE-1234-1008",
+ "UNKNOWN",
+ score=2.5,
+ cvss_version=3,
+ cvss_vector="CVSS3.0/C:H/I:L/A:M",
+ data_source="NVD",
+ last_modified="12-12-2020",
+ metric={
+ "EPSS": [0.03895, "0.37350"],
+ },
+ ),
+ ],
+ paths={""},
+ ),
+ }
+
+ def test_output_cyclonedx(self):
+ """Test VEX output generation"""
+
+ vexgen = VEXGenerate(
+ "dummy-product",
+ "1.0",
+ "dummy-vendor",
+ "generated_cyclonedx_vex.json",
+ "cyclonedx",
+ self.FORMATTED_DATA,
+ )
+ vexgen.generate_vex()
+ with open("generated_cyclonedx_vex.json") as f:
+ json_data = json.load(f)
+ # remove timestamp and serialNumber from generated json as they are dynamic
+ json_data.get("metadata", {}).pop("timestamp", None)
+ json_data.pop("serialNumber", None)
+ for vulnerability in json_data.get("vulnerabilities", []):
+ vulnerability.pop("published", None)
+ vulnerability.pop("updated", None)
+
+ with open(str(VEX_PATH / "test_cyclonedx_vex.json")) as f:
+ expected_json = json.load(f)
+ # remove timestamp and serialNumber from expected json as they are dynamic
+ expected_json.get("metadata", {}).pop("timestamp", None)
+ expected_json.pop("serialNumber", None)
+ for vulnerability in expected_json.get("vulnerabilities", []):
+ vulnerability.pop("published", None)
+ vulnerability.pop("updated", None)
+
+ assert json_data == expected_json
+
+ Path("generated_cyclonedx_vex.json").unlink()
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/test/vex/test_cyclonedx_vex.json b/test/vex/test_cyclonedx_vex.json
new file mode 100644
index 0000000000..66a1183938
--- /dev/null
+++ b/test/vex/test_cyclonedx_vex.json
@@ -0,0 +1,125 @@
+{
+ "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
+ "bomFormat": "CycloneDX",
+ "specVersion": "1.6",
+ "serialNumber": "urn:uuid:9dbd4a19-324a-4ac6-b29b-37202d2bcd90",
+ "version": 1,
+ "metadata": {
+ "timestamp": "2024-06-14T22:39:24Z",
+ "tools": {
+ "components": [
+ {
+ "name": "lib4vex",
+ "version": "0.1.0",
+ "type": "application"
+ }
+ ]
+ },
+ "properties": [
+ {
+ "name": "Revision_1",
+ "value": "Initial version"
+ }
+ ],
+ "component": {
+ "type": "application",
+ "bom-ref": "CDXRef-DOCUMENT",
+ "name": "dummy-product"
+ }
+ },
+ "vulnerabilities": [
+ {
+ "bom-ref": "product0@1.0",
+ "id": "CVE-1234-1004",
+ "source": {
+ "name": "NVD",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1004"
+ },
+ "description": "",
+ "published": "2024-06-14T22:39:24Z",
+ "updated": "2024-06-14T22:39:24Z",
+ "analysis": {
+ "state": "in_triage",
+ "detail": ""
+ },
+ "affects": [
+ {
+ "ref": "urn:cbt:1/vendor0#product0:1.0",
+ "versions": {
+ "status": "unknown"
+ }
+ }
+ ]
+ },
+ {
+ "bom-ref": "product0@1.0",
+ "id": "CVE-1234-1005",
+ "source": {
+ "name": "NVD",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1005"
+ },
+ "description": "",
+ "published": "2024-06-14T22:39:24Z",
+ "updated": "2024-06-14T22:39:24Z",
+ "analysis": {
+ "state": "not_affected",
+ "detail": "Detail field populated.",
+ "justification": "code_not_reachable"
+ },
+ "affects": [
+ {
+ "ref": "urn:cbt:1/vendor0#product0:1.0",
+ "versions": {
+ "status": "unaffected"
+ }
+ }
+ ]
+ },
+ {
+ "bom-ref": "product0@2.8.6",
+ "id": "CVE-1234-1007",
+ "source": {
+ "name": "NVD",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1007"
+ },
+ "description": "",
+ "published": "2024-06-14T22:39:24Z",
+ "updated": "2024-06-14T22:39:24Z",
+ "analysis": {
+ "state": "resolved",
+ "detail": "Data field populated."
+ },
+ "affects": [
+ {
+ "ref": "urn:cbt:1/vendor0#product0:2.8.6",
+ "versions": {
+ "status": "affected"
+ }
+ }
+ ]
+ },
+ {
+ "bom-ref": "product0@2.8.6",
+ "id": "CVE-1234-1008",
+ "source": {
+ "name": "NVD",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1008"
+ },
+ "description": "",
+ "published": "2024-06-14T22:39:24Z",
+ "updated": "2024-06-14T22:39:24Z",
+ "analysis": {
+ "state": "in_triage",
+ "detail": ""
+ },
+ "affects": [
+ {
+ "ref": "urn:cbt:1/vendor0#product0:2.8.6",
+ "versions": {
+ "status": "unknown"
+ }
+ }
+ ]
+ }
+ ]
+}