Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .dryrunsecurity.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ allowedAuthors:
- blakeowens
notificationList:
- '@mtesauro'
- '@grendel513'
- '@grendel513'
4 changes: 0 additions & 4 deletions docs/content/en/getting_started/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ godojo installations

If you have installed DefectDojo on "iron" and wish to upgrade the installation, please see the [instructions in the repo](https://github.com/DefectDojo/godojo/blob/master/docs-and-scripts/upgrading.md).

## Upgrading to DefectDojo Version 2.28.x.

There are no special instruction for upgrading to 2.28.0. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.28.0) for the contents of the release.

## Upgrading to DefectDojo Version 2.27.x.

There are no special instruction for upgrading to 2.27.0. Check the [Release Notes](https://github.com/DefectDojo/django-DefectDojo/releases/tag/2.27.0) for the contents of the release.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: "Jfrog xray on demand binary Scan"
toc_hide: true
---
Import the JSON format for the \"Jfrog xray on demand binary Scan\" file. Use this importer for Xray version 2.X
--
jfron file documentation

https://jfrog.com/help/r/jfrog-cli/on-demand-binary-scan
10 changes: 10 additions & 0 deletions dojo/fixtures/defect_dojo_sample_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -8620,6 +8620,16 @@
}
},
{
"model": "dojo.test_type",
"pk": 149,
"fields": {
"name": "Jfrog Xray On Demand Binary Scan",
"static_tool": false,
"dynamic_tool": false,
"active": true
}
},
{
"model": "dojo.tagulous_product_tags",
"pk": 1,
"fields": {
Expand Down
2 changes: 2 additions & 0 deletions dojo/settings/settings.dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,7 @@ def saml2_attrib_map_format(dict):
'GitLab Dependency Scanning Report': ['title', 'vulnerability_ids', 'file_path', 'component_name', 'component_version'],
'SpotBugs Scan': ['cwe', 'severity', 'file_path', 'line'],
'JFrog Xray Unified Scan': ['vulnerability_ids', 'file_path', 'component_name', 'component_version'],
'Jfrog Xray On Demand Binary Scan': ["title", "description", "component_name", "component_version"],
'Scout Suite Scan': ['file_path', 'vuln_id_from_tool'], # for now we use file_path as there is no attribute for "service"
'AWS Security Hub Scan': ['unique_id_from_tool'],
'Meterian Scan': ['cwe', 'component_name', 'component_version', 'description', 'severity'],
Expand Down Expand Up @@ -1415,6 +1416,7 @@ def saml2_attrib_map_format(dict):
'Checkov Scan': DEDUPE_ALGO_HASH_CODE,
'SpotBugs Scan': DEDUPE_ALGO_HASH_CODE,
'JFrog Xray Unified Scan': DEDUPE_ALGO_HASH_CODE,
'Jfrog Xray On Demand Binary Scan': DEDUPE_ALGO_HASH_CODE,
'Scout Suite Scan': DEDUPE_ALGO_HASH_CODE,
'AWS Security Hub Scan': DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL,
'Meterian Scan': DEDUPE_ALGO_HASH_CODE,
Expand Down
Empty file.
224 changes: 224 additions & 0 deletions dojo/tools/jfrog_xray_on_demand_binary_scan/parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import json
import re

from cvss import CVSS3

from dojo.models import Finding


class JfrogXrayOnDemandBinaryScanParser(object):
"""jfrog_xray_scan JSON reports"""

def get_scan_types(self):
return ["Jfrog Xray On Demand Binary Scan"]

def get_label_for_scan_types(self, scan_type):
return scan_type

def get_description_for_scan_types(self, scan_type):
return "Import Xray findings in JSON format."

def get_findings(self, json_output, test):
tree = json.load(json_output)
return self.get_items(tree, test)

def get_items(self, tree, test):
items = {}
for data in tree:
if "vulnerabilities" in data:
vulnerability_tree = data["vulnerabilities"]

for node in vulnerability_tree:
item = get_item(node, test)

title_cve = "No CVE"
if "cves" in tree:
if "cve" in tree["cves"][0]:
title_cve = tree["cve"]

unique_key = node.get("issue_id", "") + node.get("summary", "") + title_cve
items[unique_key] = item

return list(items.values())


def decode_cwe_number(value):
match = re.match(r"CWE-\d+", value, re.IGNORECASE)
if match is None:
return 0
return int(match[0].rsplit("-")[1])


def get_servery(vulnerability):
if "severity" in vulnerability:
if vulnerability["severity"] == "Unknown":
severity = "Info"
else:
severity = vulnerability["severity"].title()
else:
severity = "Info"
return severity


def get_references(vulnerability):
ref = ""
if "references" in vulnerability:
references = vulnerability["references"]
for reference in references:
ref += reference + "\n"
return ref


def get_remediation(extended_information):
remediation = ""
if "remediation" in extended_information:
remediation = "\n**Remediation**\n"
remediation += extended_information["remediation"] + "\n"
return remediation


def get_severity_justification(vulnerability):
severity_desc = ""
remediation = ""
extended_information = vulnerability.get("extended_information")
if extended_information:
remediation += get_remediation(extended_information)
if "short_description" in extended_information:
severity_desc = "**short description**\n"
severity_desc += extended_information["short_description"] + "\n"
if "full_description" in extended_information:
severity_desc = "**full description**\n"
severity_desc += extended_information["full_description"] + "\n"
if "jfrog_research_severity" in extended_information:
severity_desc = "**jfrog research severity**\n"
severity_desc += extended_information["jfrog_research_severity"] + "\n"
if "jfrog_research_severity_reasons" in extended_information:
severity_desc = "**jfrog research severity reasons**\n"
for item in extended_information["jfrog_research_severity_reasons"]:
severity_desc += item["name"] + "\n" if item.get("name") else ""
severity_desc += item["description"] + "\n" if item.get("description") else ""
return severity_desc, remediation


def get_component(vulnerability):
mitigation = ""
gav = ""
impact = "**Impact paths**\n"
if "components" in vulnerability:
components = vulnerability["components"]
gav = next(iter(components))
component = components[gav]
fixed_versions = component.get("fixed_versions")
if fixed_versions:
mitigation = "**Versions containing a fix:**\n"
mitigation = mitigation + "\n".join(fixed_versions)
if "impact_paths" in component:
impact_paths = component["impact_paths"][0]
for item in impact_paths:
if "component_id" in item:
component_id = item["component_id"]
impact = impact + "\n" + component_id
if "full_path" in item:
full_path = item["full_path"]
impact = impact + "\n" + full_path
return gav, mitigation, impact


def get_version_vulnerability(vulnerability):
if "vulnerable_versions" in vulnerability["component_versions"]:
extra_desc = "\n**Versions that are vulnerable:**\n"
extra_desc += "\n".join(vulnerability["component_versions"]["vulnerable_versions"])
return extra_desc
return "None"


def get_provider(vulnerabiity):
if "component_versions" in vulnerabiity:
provider = vulnerabiity.get("component_versions").get("more_details").get("provider")
if provider:
provider += f"\n**Provider:** {provider}"
return provider
return ""


def get_etx(vulnerability):
if "EXT" in vulnerability:
return vulnerability["EXT"]
return ""


def get_cve(vulnerability):
if "cves" in vulnerability:
cves = vulnerability["cves"]
return cves
return []


def get_item(vulnerability, test):
severity_justification, remediation = get_severity_justification(vulnerability)
severity = get_servery(vulnerability)
references = get_references(vulnerability)
vulnerability_ids = list()
cwe = None
cvssv3 = None
cvss_v3 = "No CVSS v3 score."
extra_desc = ""
# Some entries have no CVE entries, despite they exist. Example CVE-2017-1000502.
cves = get_cve(vulnerability)
if len(cves) > 0:
for item in cves:
if item.get("cve"):
vulnerability_ids.append(item.get("cve"))
# take only the first one for now, limitation of DD model.
if len(cves[0].get("cwe", [])) > 0:
cwe = decode_cwe_number(cves[0].get("cwe", [])[0])
if "cvss_v3" in cves[0]:
cvss_v3 = cves[0]["cvss_v3"]
# this dedicated package will clean the vector
cvssv3 = CVSS3.from_rh_vector(cvss_v3).clean_vector()

extra_desc += get_provider(vulnerability)
component_name, mitigation, impact = get_component(vulnerability)
component_version = get_etx(vulnerability)

# The 'id' field is empty? (at least in my sample file)
if vulnerability_ids:
if vulnerability.get("id"):
title = (
vulnerability["id"]
+ " - "
+ str(vulnerability_ids[0])
+ " - "
+ component_name
+ ":"
+ component_version
)
else:
title = str(vulnerability_ids[0]) + " - " + component_name + ":" + component_version
else:
if vulnerability.get("id"):
title = vulnerability["id"] + " - " + component_name + ":" + component_version
else:
title = "No CVE - " + component_name + ":" + component_version

# create the finding object
finding = Finding(
title=title,
cwe=cwe,
test=test,
severity_justification=severity_justification,
severity=severity,
description=(vulnerability["summary"] + extra_desc).strip(),
mitigation=mitigation + remediation,
component_name=component_name,
component_version=component_version,
impact=impact,
references=references,
file_path=vulnerability.get("source_comp_id"),
static_finding=True,
dynamic_finding=False,
cvssv3=cvssv3,
)
if vulnerability_ids:
finding.unsaved_vulnerability_ids = vulnerability_ids
return finding
112 changes: 112 additions & 0 deletions unittests/scans/jfrog_xray_on_demand_binary_scan/many_vulns.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
[
{
"scan_id": "dd8f-4927-5db6-fb188ae8d984",
"vulnerabilities": [
{
"cves": [
{
"cve": "CVE-2017-8923",
"cvss_v2_score": "5.0",
"cvss_v2_vector": "CVSS:2.0/AV:N/AC:L/Au:N/C:N/I:N/A:P",
"cvss_v3_score": "7.5",
"cvss_v3_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
}
],
"summary": "Summary of test",
"severity": "High",
"components": {
"gav://org.yaml:snakeyaml:1.16": {
"fixed_versions": [
"[1.26]"
],
"impact_paths": [
[
{
"component_id": "gav://co.com.test.com"
},
{
"component_id": "gav://co.com.test.com",
"full_path": "lib/snakeyaml-1.16.jar"
}
]
]
}
},
"issue_id": "XRAY-92904",
"references": [
"https://test.com.co"
]
},
{
"cves": [
{
"cve": "CVE-2014-0114",
"cvss_v2_score": "7.5",
"cvss_v2_vector": "CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P"
}
],
"summary": "Summary test",
"severity": "High",
"components": {
"gav://test": {
"fixed_versions": [
"[1.9.4]"
],
"impact_paths": [
[
{
"component_id": "gav://co.com.test.test:core:1.0.0-test"
},
{
"component_id": "gav://test",
"full_path": "lib/commons-beanutils-1.9.2.jar"
}
]
]
}
},
"issue_id": "XRAY-55616",
"references": [
"https://test.com.co"
]
},
{
"cves": [
{
"cvss_v2_score": "7.5",
"cvss_v2_vector": "CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P"
}
],
"summary": "Summary test",
"severity": "High",
"components": {
"test_item": {
"fixed_versions": [
"[1.2.8.RELEASE]",
"[1.3.1.RELEASE]"
],
"impact_paths": [
[
{
"component_id": "gav://co.com.test.test:core:1.0.0-test"
},
{
"component_id": "gav://test.com.co",
"full_path": "lib/test/libtest"
}
]
]
}
},
"issue_id": "XRAY-79870",
"references": [
"https://test.com.co"
]
}
],
"component_id": "gav://co.com.test.test:core:1.0.0-test",
"package_type": "Maven",
"status": "completed"
}
]

Loading