Skip to content
Merged
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
3 changes: 3 additions & 0 deletions scanpipe/pipes/cyclonedx.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from cyclonedx.model import license as cdx_license_model
from cyclonedx.model.bom import Bom
from cyclonedx.schema import SchemaVersion
from cyclonedx.schema.schema import BaseSchemaVersion
from cyclonedx.validation import ValidationError
from cyclonedx.validation.json import JsonStrictValidator
from defusedxml import ElementTree as SafeElementTree
Expand Down Expand Up @@ -184,10 +185,12 @@ def cyclonedx_component_to_package_data(
affected_by_vulnerabilities = []
if affected_by := vulnerabilities.get(bom_ref):
for cdx_vulnerability in affected_by:
cdx_vulnerability_json = cdx_vulnerability.as_json(view_=BaseSchemaVersion)
affected_by_vulnerabilities.append(
{
"vulnerability_id": str(cdx_vulnerability.id),
"summary": cdx_vulnerability.description,
"cdx_vulnerability_data": json.loads(cdx_vulnerability_json),
}
)

Expand Down
55 changes: 35 additions & 20 deletions scanpipe/templates/scanpipe/tabset/tab_vulnerabilities.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<table class="table is-bordered is-striped is-narrow is-hoverable is-fullwidth">
<thead>
<tr>
<th style="width: 210px;">Affected by</th>
<th style="width: 220px;">Affected by</th>
<th>Summary</th>
<th style="width: 210px;">Aliases</th>
<th>Analysis</th>
</tr>
</thead>
<tbody>
Expand All @@ -15,28 +15,43 @@
{{ vulnerability.vulnerability_id }}
<i class="fa-solid fa-up-right-from-square is-small"></i>
</a>
<ul class="list-unstyled mb-0">
{% for alias in aliases %}
<li>
{% if alias|slice:":3" == "CVE" %}
<a href="https://nvd.nist.gov/vuln/detail/{{ alias }}" target="_blank">{{ alias }}
<i class="fa-solid fa-up-right-from-square mini"></i>
</a>
{% elif alias|slice:":4" == "GHSA" %}
<a href="https://github.com/advisories/{{ alias }}" target="_blank">{{ alias }}
<i class="fa-solid fa-up-right-from-square mini"></i>
</a>
{% elif alias|slice:":3" == "NPM" %}
<a href="https://github.com/nodejs/security-wg/blob/main/vuln/npm/{{ alias|slice:"4:" }}.json" target="_blank">{{ alias }}
<i class="fa-solid fa-up-right-from-square mini"></i>
</a>
{% else %}
{{ alias }}
{% endif %}
</li>
{% endfor %}
</ul>
</td>
<td>
{{ vulnerability.summary }}
</td>
<td>
{% for alias in vulnerability.aliases %}
{% if alias|slice:":3" == "CVE" %}
<a href="https://nvd.nist.gov/vuln/detail/{{ alias }}" target="_blank">{{ alias }}
<i class="fa-solid fa-up-right-from-square is-small"></i>
</a>
{% elif alias|slice:":4" == "GHSA" %}
<a href="https://github.com/advisories/{{ alias }}" target="_blank">{{ alias }}
<i class="fa-solid fa-up-right-from-square is-small"></i>
</a>
{% elif alias|slice:":3" == "NPM" %}
<a href="https://github.com/nodejs/security-wg/blob/main/vuln/npm/{{ alias|slice:"4:" }}.json" target="_blank">{{ alias }}
<i class="fa-solid fa-up-right-from-square is-small"></i>
</a>
{% if vulnerability.summary %}
{% if vulnerability.summary|length > 150 %}
<details>
<summary>{{ vulnerability.summary|slice:":150" }}...</summary>
{{ vulnerability.summary|slice:"150:" }}
</details>
{% else %}
{{ alias }}
{{ vulnerability.summary }}
{% endif %}
<br>
{% endif %}
</td>
<td>
{% for key, value in vulnerability.cdx_vulnerability.analysis.items %}
<strong>{{ key }}:</strong> {{ value }}{% if not forloop.last %}<br>{% endif %}
{% endfor %}
</td>
</tr>
Expand Down
21 changes: 16 additions & 5 deletions scanpipe/tests/pipes/test_cyclonedx.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,24 @@ def test_scanpipe_cyclonedx_resolve_cyclonedx_packages_vulnerabilities(self):
self.assertEqual(1, len(packages))

affected_by = packages[0]["affected_by_vulnerabilities"]
self.assertEqual("CVE-2005-2541", affected_by[0]["vulnerability_id"])
self.assertEqual(
"Tar 1.15.1 does not properly warn the user when...",
affected_by[0]["summary"],
)
self.assertIn("cdx_vulnerability_data", affected_by[0])
cdx_vulnerability_data = affected_by[0]["cdx_vulnerability_data"]
expected = [
{
"vulnerability_id": "CVE-2005-2541",
"summary": "Tar 1.15.1 does not properly warn the user when...",
}
"advisories",
"affects",
"description",
"id",
"published",
"ratings",
"source",
"updated",
]
self.assertEqual(expected, affected_by)
self.assertEqual(expected, sorted(cdx_vulnerability_data.keys()))

def test_scanpipe_cyclonedx_resolve_cyclonedx_packages_pre_validation(self):
# This SBOM includes multiple deserialization issues that are "fixed"
Expand Down
21 changes: 16 additions & 5 deletions scanpipe/tests/test_pipelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -1638,13 +1638,24 @@ def test_scanpipe_load_sbom_pipeline_cyclonedx_with_vulnerabilities(self):

self.assertEqual(1, project1.discoveredpackages.count())
package = project1.discoveredpackages.get()
affected_by = package.affected_by_vulnerabilities[0]
cdx_vulnerability_data = affected_by.pop("cdx_vulnerability_data")
expected = {
"vulnerability_id": "CVE-2005-2541",
"summary": "Tar 1.15.1 does not properly warn the user when...",
}
self.assertEqual(expected, affected_by)
expected = [
{
"vulnerability_id": "CVE-2005-2541",
"summary": "Tar 1.15.1 does not properly warn the user when...",
}
"advisories",
"affects",
"description",
"id",
"published",
"ratings",
"source",
"updated",
]
self.assertEqual(expected, package.affected_by_vulnerabilities)
self.assertEqual(expected, sorted(cdx_vulnerability_data.keys()))

@mock.patch("scanpipe.pipes.purldb.request_post")
@mock.patch("uuid.uuid4")
Expand Down