Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Udated Anchorectl_vuln parser to also parse Anchore Enterprise Vulnerability report #11688

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
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
133 changes: 40 additions & 93 deletions dojo/tools/anchorectl_vulns/parser.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import json

from dojo.models import Finding


class AnchoreCTLVulnsParser:

Check failure on line 5 in dojo/tools/anchorectl_vulns/parser.py

View workflow job for this annotation

GitHub Actions / ruff-linting

Ruff (I001)

dojo/tools/anchorectl_vulns/parser.py:1:1: I001 Import block is un-sorted or un-formatted
def get_scan_types(self):
return ["AnchoreCTL Vuln Report"]

Expand All @@ -16,117 +15,65 @@
def get_findings(self, filename, test):
data = json.load(filename)
dupes = {}
for item in data:
vulnerability_id = item.get("vuln")

title = (
item["vuln"]
+ " - "
+ item["package"]
+ "("
+ item["packageType"]
+ ")"
)
metadata = data.get("metadata", {})
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems the old format has a list at the top level, and the .get() here is causing (the old) tests to fail. The data.get() two lines below will cause the same issue.

image_digest = metadata.get("imageDigest", "None")
vulnerabilities = data.get("securityEvaluation", data)

for vuln in vulnerabilities:
vulnerability_id = vuln.get("vulnerabilityId", vuln.get("vuln"))
title = f"{vulnerability_id} - {vuln['package']} ({vuln['packageType']})"

# Finding details information
# depending on version image_digest/imageDigest
findingdetail = (
"**Image hash**: " + item.get("imageDigest", "None") + "\n\n"
)
findingdetail += "**Package**: " + item["package"] + "\n\n"
findingdetail += (
"**Package path**: " + item["packagePath"] + "\n\n"
)
findingdetail += (
"**Package type**: " + item["packageType"] + "\n\n"
)
findingdetail += (
"**Feed**: " + item["feed"] + "/" + item["feedGroup"] + "\n\n"
)
findingdetail += "**CPE**: " + item["packageCpe"] + "\n\n"
findingdetail += (
"**Description**: "
+ item.get("description", "<None>")
+ "\n\n"
)
findingdetail = f"**Image hash**: {image_digest}\n\n"
findingdetail += f"**Package**: {vuln['package']}\n\n"
findingdetail += f"**Package path**: {vuln.get('path', vuln.get('packagePath', 'N/A'))}\n\n"
findingdetail += f"**Package type**: {vuln['packageType']}\n\n"
findingdetail += f"**Feed**: {vuln.get('feed', 'N/A')}/{vuln.get('feedGroup', 'N/A')}\n\n"
findingdetail += f"**CPE**: {vuln.get('packageCpe', 'N/A')}\n\n"
findingdetail += f"**Description**: {vuln.get('description', '<None>')}\n\n"

sev = item["severity"]
if sev == "Negligible" or sev == "Unknown":
sev = vuln["severity"]
if sev in ["Negligible", "Unknown"]:
sev = "Info"

if item["fix"] != "None":
mitigation = (
"Upgrade to " + item["packageName"] + " " + item["fix"] + "\n"
)
else:
mitigation = (
"No fix available" + "\n"
)
mitigation = f"Upgrade to {vuln.get('fix', vuln.get('fixAvailable', 'No fix available'))}\n"
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a problem per se, but wondering if the mitigation string "Upgrade to None" (in the case where no fix is available) is ideal.

mitigation += f"URL: {vuln.get('url', vuln.get('link', 'N/A'))}\n"

cvssv3_base_score = None
if item["feed"] == "nvdv2" or item["feed"] == "vulnerabilities":
if "nvdData" in item and len(item["nvdData"]) > 0:
cvssv3_base_score = item["nvdData"][0]["cvssV3"][
"baseScore"
]
cvss_base_score = None
if vuln.get("feed") in ["nvdv2", "vulnerabilities"]:
if vuln.get("nvdData"):
cvss_base_score = vuln["nvdData"][0].get("cvssV3", {}).get("baseScore")
else:
# there may be other keys, but taking a best guess here
if "vendorData" in item and len(item["vendorData"]) > 0:
# sometimes cvssv3 in 1st element will have -1 for "not
# set", but have data in the 2nd array item
if (
"cvssV3" in item["vendorData"][0]
and item["vendorData"][0]["cvssV3"]["baseScore"] != -1
):
cvssv3_base_score = item["vendorData"][0]["cvssV3"][
"baseScore"
]
elif len(item["vendorData"]) > 1:
if (
"cvssV3" in item["vendorData"][1]
and item["vendorData"][1]["cvssV3"]["baseScore"]
!= -1
):
cvssv3_base_score = item["vendorData"][1][
"cvssV3"
]["baseScore"]

references = item["url"]
for vendor in vuln.get("vendorData", []):
if vendor.get("cvssV3", {}).get("baseScore", -1) != -1:
cvss_base_score = vendor["cvssV3"]["baseScore"]
break

dupe_key = "|".join(
[
item.get(
"imageDigest", "None",
), # depending on version image_digest/imageDigest
item["feed"],
item["feedGroup"],
item["packageName"],
item["packageVersion"],
item["packagePath"],
item["vuln"],
],
)
references = vuln.get("url", vuln.get("link", "N/A"))

if dupe_key in dupes:
find = dupes[dupe_key]
else:
dupes[dupe_key] = True
dupe_key = "|".join([
image_digest,
vulnerability_id,
vuln["package"],
vuln.get("path", vuln.get("packagePath", "N/A")),
])

if dupe_key not in dupes:
find = Finding(
title=title,
test=test,
cvssv3_score=cvssv3_base_score,
cvssv3_score=cvss_base_score,
description=findingdetail,
severity=sev,
mitigation=mitigation,
references=references,
file_path=item["packagePath"],
component_name=item["packageName"],
component_version=item["packageVersion"],
url=item.get("url"),
file_path=vuln.get("path", vuln.get("packagePath", "N/A")),
component_name=vuln["package"],
component_version=vuln.get("packageVersion", "Unknown"),
url=vuln.get("url", vuln.get("link")),
static_finding=True,
dynamic_finding=False,
vuln_id_from_tool=item.get("vuln"),
vuln_id_from_tool=vulnerability_id,
)
if vulnerability_id:
find.unsaved_vulnerability_ids = [vulnerability_id]
Expand Down
Loading
Loading