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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions cve_bin_tool/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,19 +384,19 @@ def main(argv=None):
"--product",
action="store",
default="",
help="Product Name",
help="Product Name (default: 'unknown' when not specified)",
)
vex_output_group.add_argument(
"--release",
action="store",
default="",
help="Release Version",
help="Release Version (default: '0.0' when not specified)",
)
vex_output_group.add_argument(
"--vendor",
action="store",
default="",
help="Vendor/Supplier of Product",
help="Vendor/Supplier of Product (default: 'unknown' when not specified)",
)
vex_output_group.add_argument(
"-rr",
Expand Down Expand Up @@ -1262,21 +1262,21 @@ def main(argv=None):
if args["vex_output"] and not args["vex_type"]:
# default vex_type is cyclonedx
args["vex_type"] = "cyclonedx"
if args["product"] and args["release"] and args["vendor"]:
if args["vex_file"]:
vex_product_info["revision_reason"] = args["revision_reason"]
else:
if not (args["product"] and args["release"] and args["vendor"]):
LOGGER.warning(
"No --product, --release, or --vendor provided for VEX generation. "
"Using defaults: product='unknown', vendor='unknown', release='0.0'."
Comment on lines +1270 to +1271
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

The warning text is misleading: this branch runs when any of --product/--release/--vendor is missing, but the message says none were provided. Consider rewording to indicate which fields are missing (or say "Missing --product/--release/--vendor; using defaults...") to avoid confusing users who supplied one or two of the flags.

Suggested change
"No --product, --release, or --vendor provided for VEX generation. "
"Using defaults: product='unknown', vendor='unknown', release='0.0'."
"One or more of --product, --release, or --vendor were not provided for VEX generation. "
"Using defaults for missing values: product='unknown', vendor='unknown', release='0.0'."

Copilot uses AI. Check for mistakes.
)
vex_product_info = {
"product": args["product"],
"release": args["release"],
"vendor": args["vendor"],
"product": args["product"] or "unknown",
"release": args["release"] or "0.0",
"vendor": args["vendor"] or "unknown",
"revision_reason": args["revision_reason"],
"sbom_serial_number": sbom_serial_number,
}
elif args["vex_file"]:
vex_product_info["revision_reason"] = args["revision_reason"]
else:
LOGGER.error(
"Please provide --product, --release and --vendor for VEX generation"
)
return ERROR_CODES[InsufficientArgs]

if args["vex_file"] and args["filter_triage"]:
cve_scanner.filter_triage_data()
Expand Down
35 changes: 35 additions & 0 deletions test/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
CVE-bin-tool CLI tests
"""
import importlib
import json
import logging
import os
import re
Expand Down Expand Up @@ -109,6 +110,40 @@ def test_usage(self):
main(["cve-bin-tool"])
assert e.value.args[0] == ERROR_CODES[InsufficientArgs]

def test_vex_output_without_product_vendor_release(self, caplog, tmp_path):
"""Test that VEX generation works without --product, --vendor, --release.
Defaults (product='unknown', vendor='unknown', release='0.0') should be used
and a warning should be logged instead of erroring out."""
vex_out = str(tmp_path / "default_product.vex.json")
CSV_PATH = str(Path(__file__).parent.resolve() / "csv" / "test_triage.csv")
with caplog.at_level(logging.WARNING):
result = main(
[
"cve-bin-tool",
"--offline",
"--input-file",
CSV_PATH,
"--vex-type",
"cyclonedx",
"--vex-output",
vex_out,
]
)
# Should not fail with InsufficientArgs — defaults must be used
assert result != ERROR_CODES[InsufficientArgs]
# A warning should be logged about using defaults
assert any(
"Using defaults" in record.message for record in caplog.records
), "Expected warning about default product/vendor/release not found in logs"
# The VEX file should have been created with default values
if Path(vex_out).exists():
with open(vex_out) as f:
vex_data = json.load(f)
component = vex_data.get("metadata", {}).get("component", {})
assert component.get("name") == "unknown"
assert component.get("version") == "0.0"
assert component.get("supplier", {}).get("name") == "unknown"
Comment on lines +139 to +145
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

This test only inspects the VEX output if the file exists, which can let failures slip by silently. Since the purpose is to ensure VEX generation succeeds, assert that vex_out exists (and ideally validate its contents) unconditionally.

Suggested change
if Path(vex_out).exists():
with open(vex_out) as f:
vex_data = json.load(f)
component = vex_data.get("metadata", {}).get("component", {})
assert component.get("name") == "unknown"
assert component.get("version") == "0.0"
assert component.get("supplier", {}).get("name") == "unknown"
assert Path(vex_out).exists(), "Expected VEX output file to be created"
with open(vex_out) as f:
vex_data = json.load(f)
component = vex_data.get("metadata", {}).get("component", {})
assert component.get("name") == "unknown"
assert component.get("version") == "0.0"
assert component.get("supplier", {}).get("name") == "unknown"

Copilot uses AI. Check for mistakes.

def test_version(self):
"""Test that the version returns 0"""
with pytest.raises(SystemExit) as e:
Expand Down
22 changes: 22 additions & 0 deletions test/test_vex.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,28 @@ def test_output_cyclonedx(self):

Path("generated_cyclonedx_vex.json").unlink()

def test_output_cyclonedx_default_product_info(self):
"""Test VEX output generation uses default product/vendor/release when not specified"""
Comment on lines +126 to +127
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

The test name/docstring say defaults are used "when not specified", but the test passes explicit values ("unknown"/"0.0"). Consider renaming/rewording the test to reflect what it's actually validating, or adjust it to exercise the defaulting behavior at the layer that implements it.

Suggested change
def test_output_cyclonedx_default_product_info(self):
"""Test VEX output generation uses default product/vendor/release when not specified"""
def test_output_cyclonedx_with_provided_product_info(self):
"""Test VEX output generation uses the provided product/vendor/release values"""

Copilot uses AI. Check for mistakes.

vexgen = VEXGenerate(
"unknown",
"0.0",
"unknown",
"generated_cyclonedx_default_vex.json",
"cyclonedx",
self.FORMATTED_DATA,
)
vexgen.generate_vex()
with open("generated_cyclonedx_default_vex.json") as f:
json_data = json.load(f)

component = json_data.get("metadata", {}).get("component", {})
assert component.get("name") == "unknown"
assert component.get("version") == "0.0"
assert component.get("supplier", {}).get("name") == "unknown"

Path("generated_cyclonedx_default_vex.json").unlink()

def test_output_openvex(self):
"""Test VEX output generation"""

Expand Down
Loading