Skip to content

Commit

Permalink
fix(general): fix duplicate components in CycloneDX report (bridgecre…
Browse files Browse the repository at this point in the history
…wio#5705)

fix duplicate components in CycloneDX report
  • Loading branch information
gruebel authored Oct 31, 2023
1 parent d5040bc commit ea22e1f
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 7 deletions.
10 changes: 3 additions & 7 deletions checkov/common/output/cyclonedx.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,8 @@ def create_bom(self) -> Bom:
continue
component = self.create_component(check_type=report.check_type, resource=check)

if bom.has_component(component=component):
component = (
bom.get_component_by_purl( # type:ignore[assignment] # the previous line checks, if exists
purl=component.purl
)
)
if existing_component := bom.get_component_by_purl(purl=component.purl):
component = existing_component
else:
bom.components.add(component)

Expand All @@ -121,7 +117,7 @@ def create_bom(self) -> Bom:
for resource in sorted(report.extra_resources):
component = self.create_component(check_type=report.check_type, resource=resource)

if not bom.has_component(component=component):
if not bom.get_component_by_purl(purl=component.purl):
bom.components.add(component)

if is_image_report:
Expand Down
68 changes: 68 additions & 0 deletions tests/common/output/test_cyclonedx_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,74 @@ def test_sca_packages_cyclonedx_bom():
assert record.file_line_range == [2, 6]
assert output


def test_duplicate_sca_packages_cyclonedx_bom():
# given
rootless_file_path = "requirements.txt"
file_abs_path = "/path/to/requirements.txt"
check_class = "checkov.sca_package.scanner.Scanner"
vulnerability_details = {
"id": "CVE-2019-19844",
"status": "fixed in 3.0.1, 2.2.9, 1.11.27",
"cvss": 9.8,
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"description": "Django before 1.11.27, 2.x before 2.2.9, and 3.x before 3.0.1 allows account takeover. ...",
"severity": "moderate",
"packageName": "django",
"packageVersion": "1.2",
"link": "https://nvd.nist.gov/vuln/detail/CVE-2019-19844",
"riskFactors": ["Attack complexity: low", "Attack vector: network", "Critical severity", "Has fix"],
"impactedVersions": ["<1.11.27"],
"publishedDate": "2019-12-18T20:15:00+01:00",
"discoveredDate": "2019-12-18T19:15:00Z",
"fixDate": "2019-12-18T20:15:00+01:00",
}
package_1 = {
"package_registry": "https://registry.npmjs.org/",
"is_private_registry": False,
"linesNumbers": [2, 3],
}
package_2 = {
"package_registry": "https://registry.npmjs.org/",
"is_private_registry": False,
"linesNumbers": [5, 6],
}

record_1 = create_report_cve_record(
rootless_file_path=rootless_file_path,
file_abs_path=file_abs_path,
check_class=check_class,
vulnerability_details=vulnerability_details,
licenses="OSI_BDS",
package=package_1,
file_line_range=get_package_lines(package_1),
)
record_2 = create_report_cve_record(
rootless_file_path=rootless_file_path,
file_abs_path=file_abs_path,
check_class=check_class,
vulnerability_details=vulnerability_details,
licenses="OSI_BDS",
package=package_2,
file_line_range=get_package_lines(package_2),
)

report = Report(CheckType.SCA_PACKAGE)
report.add_resource(record_1.resource)
report.add_record(record_1)
report.add_resource(record_2.resource)
report.add_record(record_2)

# when
cyclonedx = CycloneDX([report], "repoid/test")

# then
assert len(cyclonedx.bom.components) == 1

component = next(iter(cyclonedx.bom.components))
assert component.bom_ref.value == "pkg:pypi/repoid/test/requirements.txt/[email protected]"


def test_create_schema_version_1_3(mocker: MockerFixture):
# given
test_file = Path(__file__).parent / "fixtures/main.tf"
Expand Down

0 comments on commit ea22e1f

Please sign in to comment.