Skip to content

Commit f01c28a

Browse files
committed
support for Mayhem SARIF reports
1 parent c4daf99 commit f01c28a

File tree

9 files changed

+2990
-0
lines changed

9 files changed

+2990
-0
lines changed

dojo/tools/mayhem/__init__.py

Whitespace-only changes.

dojo/tools/mayhem/parser.py

Lines changed: 627 additions & 0 deletions
Large diffs are not rendered by default.

unittests/scans/mayhem/mayhem_api_many_vulns.sarif

Lines changed: 1705 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
3+
"version": "2.1.0",
4+
"runs": [
5+
{
6+
"tool": {
7+
"driver": {
8+
"semanticVersion": "2.31.2",
9+
"name": "mAPI",
10+
"fullName": "Mayhem for API",
11+
"rules": []
12+
}
13+
},
14+
"results": []
15+
}
16+
]
17+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
3+
"version": "2.1.0",
4+
"runs": [
5+
{
6+
"tool": {
7+
"driver": {
8+
"semanticVersion": "2.31.2",
9+
"name": "mAPI",
10+
"fullName": "Mayhem for API",
11+
"rules": [
12+
{
13+
"id": "default-credentials",
14+
"shortDescription": {
15+
"text": "Default Credentials Used"
16+
},
17+
"fullDescription": {
18+
"text": "A protected API returned a successful response using well-known default credentials."
19+
},
20+
"help": {
21+
"text": "Review the endpoint code to ensure that the required authentication code is\nrunning in all cases. If the endpoint does not require authentication, update\nthe specification to indicate as such.\n\nIf the authentication checks are performed on this endpoint, review the code\nchecking the provided credentials to ensure that default credentials are not\naccepted as valid. Ensure that the user-provided data is validated extensively\nbefore any authentication checks are performed. The sample response provided by\nMayhem for API as part of the bug report may point you in the right direction\nwhen trying to debug the issue. The issue may be in the underlying library, if\nany, you are using to perform validation checks.\n"
22+
},
23+
"defaultConfiguration": {
24+
"level": "error"
25+
},
26+
"properties": {
27+
"tags": [
28+
"Security",
29+
"CWE-287",
30+
"CWE-1390",
31+
"CWE-1391",
32+
"CWE-1392",
33+
"OWASP-API2"
34+
]
35+
}
36+
}
37+
]
38+
}
39+
},
40+
"results": [
41+
{
42+
"ruleId": "default-credentials",
43+
"message": {
44+
"text": "Default Credentials Used in 'GET /info'. [Details](https://app.mayhem.security/xansec/mayhem-demo/api/-/defects/2587042)",
45+
"markdown": "Default Credentials Used in 'GET /info'.\n\n# Sample Request\n\n```http\nGET /info HTTP/1.1\ncontent-length: 0\nauthorization: Basic TFItSVNETjpMUi1JU0RO\nx-mapi-program-uuid: eb3b952d-2088-4711-a86b-7995c83b8579\n\n```\n\n# Sample Response\n\n```http\nHTTP/1.1 200 OK\ndate: Wed, 18 Jun 2025 02:24:15 GMT\nserver: uvicorn\ncontent-length: 35\ncontent-type: application/json\n\n[\n \"version: 1.0.0\\n\",\n \"config: fast\"\n]\n```\n\n[Details](https://app.mayhem.security/xansec/mayhem-demo/api/-/defects/2587042)\n"
46+
},
47+
"codeFlows": [],
48+
"locations": [
49+
{
50+
"physicalLocation": {
51+
"artifactLocation": {
52+
"uri": "unknown-file",
53+
"uriBaseId": "%SRCROOT%"
54+
}
55+
}
56+
}
57+
]
58+
}
59+
]
60+
}
61+
]
62+
}

unittests/scans/mayhem/mayhem_code_many_vulns.sarif

Lines changed: 394 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"runs": [
3+
{
4+
"tool": {
5+
"driver": {
6+
"name": "Mayhem Code Security",
7+
"rules": [],
8+
"version": "2.12.0",
9+
"informationUri": "https://www.mayhem.security/"
10+
}
11+
},
12+
"results": [],
13+
"taxonomies": [
14+
{
15+
"name": "CWE",
16+
"organization": "MITRE",
17+
"taxa": [],
18+
"shortDescription": {
19+
"text": "The MITRE Common Weakness Enumeration"
20+
}
21+
}
22+
]
23+
}
24+
],
25+
"version": "2.1.0",
26+
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Documents/CommitteeSpecifications/2.1.0/sarif-schema-2.1.0.json"
27+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
{
2+
"runs": [
3+
{
4+
"tool": {
5+
"driver": {
6+
"name": "Mayhem Code Security",
7+
"rules": [
8+
{
9+
"id": "MI101",
10+
"name": "ImproperInputValidation",
11+
"defaultConfiguration": {
12+
"level": "error"
13+
},
14+
"helpUri": "https://www.mayhem.security/",
15+
"shortDescription": {
16+
"text": "The software receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly."
17+
}
18+
}
19+
],
20+
"version": "2.12.0",
21+
"informationUri": "https://www.mayhem.security/"
22+
}
23+
},
24+
"results": [
25+
{
26+
"message": {
27+
"markdown": "#0 0x7ffff7e47b1c in vfwprintf+0x23ec at ??:0:0\n#1 0x7ffff7dee26e in raise+0x1e at ??:0:0\n#2 0x7ffff7dd18ff in abort+0xdf at ??:0:0\n#3 0x5555555559a9 in ?? at ??:0:0\n#4 0x555555555ab8 in ?? at ??:0:0\n#5 0x7ffff7dd31ca in __libc_init_first+0x8a at ??:0:0\n#6 0x7ffff7dd328b in __libc_start_main+0x8b at ??:0:0\n#7 0x555555555875 in ?? at ??:0:0\n\n\n[Details](https://app.mayhem.security:443/forallsecure-demo/bazel-rules/mayhemit/10?defect=2211925)",
28+
"text": "TDID-2211925 - Improper Input Validation"
29+
},
30+
"locations": [
31+
{
32+
"physicalLocation": {
33+
"region": {
34+
"endColumn": 1,
35+
"endLine": 1,
36+
"startColumn": 1,
37+
"startLine": 1
38+
},
39+
"artifactLocation": {
40+
"uri": "unknown_file"
41+
}
42+
}
43+
}
44+
],
45+
"taxa": [
46+
{
47+
"id": "20",
48+
"toolComponent": {
49+
"name": "CWE"
50+
}
51+
}
52+
],
53+
"ruleId": "MI101"
54+
}
55+
],
56+
"taxonomies": [
57+
{
58+
"name": "CWE",
59+
"organization": "MITRE",
60+
"taxa": [
61+
{
62+
"id": "20",
63+
"help": {
64+
"text": "The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly."
65+
},
66+
"name": "Improper Input Validation",
67+
"defaultConfiguration": {
68+
"level": "error"
69+
},
70+
"fullDescription": {
71+
"text": "The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly."
72+
},
73+
"shortDescription": {
74+
"text": "The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly."
75+
}
76+
}
77+
],
78+
"shortDescription": {
79+
"text": "The MITRE Common Weakness Enumeration"
80+
}
81+
}
82+
]
83+
}
84+
],
85+
"version": "2.1.0",
86+
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Documents/CommitteeSpecifications/2.1.0/sarif-schema-2.1.0.json"
87+
}

unittests/tools/test_mayhem_parser.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from dojo.models import Finding, Test
2+
from dojo.tools.mayhem.parser import MayhemParser
3+
from unittests.dojo_test_case import DojoTestCase, get_unit_tests_scans_path
4+
5+
6+
class TestMayhemParser(DojoTestCase):
7+
def common_checks(self, finding):
8+
self.assertLessEqual(len(finding.title), 250)
9+
self.assertIn(finding.severity, Finding.SEVERITIES)
10+
if finding.cwe:
11+
self.assertIsInstance(finding.cwe, int)
12+
self.assertEqual(False, finding.static_finding) # Mayhem is DAST!
13+
self.assertEqual(True, finding.dynamic_finding) # Mayhem is DAST!
14+
15+
def test_mcode_many_report(self):
16+
with (
17+
get_unit_tests_scans_path("mayhem") / "mayhem_code_many_vulns.sarif"
18+
).open(encoding="utf-8") as testfile:
19+
parser = MayhemParser()
20+
findings = parser.get_findings(testfile, Test())
21+
self.assertEqual(8, len(findings))
22+
for finding in findings:
23+
self.common_checks(finding)
24+
25+
def test_mapi_many_report(self):
26+
with (
27+
get_unit_tests_scans_path("mayhem") / "mayhem_api_many_vulns.sarif"
28+
).open(encoding="utf-8") as testfile:
29+
parser = MayhemParser()
30+
findings = parser.get_findings(testfile, Test())
31+
self.assertEqual(20, len(findings))
32+
for finding in findings:
33+
self.common_checks(finding)
34+
35+
def test_mcode_one_report(self):
36+
with (
37+
get_unit_tests_scans_path("mayhem") / "mayhem_code_one_vuln.sarif"
38+
).open(encoding="utf-8") as testfile:
39+
parser = MayhemParser()
40+
findings = parser.get_findings(testfile, Test())
41+
self.assertEqual(1, len(findings))
42+
finding = findings[0]
43+
self.common_checks(finding)
44+
self.assertEqual(20, finding.cwe)
45+
46+
def test_mapi_one_report(self):
47+
with (
48+
get_unit_tests_scans_path("mayhem") / "mayhem_api_one_vuln.sarif"
49+
).open(encoding="utf-8") as testfile:
50+
parser = MayhemParser()
51+
findings = parser.get_findings(testfile, Test())
52+
self.assertEqual(1, len(findings))
53+
finding = findings[0]
54+
self.common_checks(finding)
55+
self.assertEqual(1392, finding.cwe)
56+
57+
def test_mcode_no_vulns_report(self):
58+
with (
59+
get_unit_tests_scans_path("mayhem") / "mayhem_code_no_vulns.sarif"
60+
).open(encoding="utf-8") as testfile:
61+
parser = MayhemParser()
62+
findings = parser.get_findings(testfile, Test())
63+
self.assertEqual(0, len(findings))
64+
65+
def test_mapi_no_vulns_report(self):
66+
with (
67+
get_unit_tests_scans_path("mayhem") / "mayhem_api_no_vulns.sarif"
68+
).open(encoding="utf-8") as testfile:
69+
parser = MayhemParser()
70+
findings = parser.get_findings(testfile, Test())
71+
self.assertEqual(0, len(findings))

0 commit comments

Comments
 (0)