Skip to content

Commit a3dc848

Browse files
committed
Add. Gitlab SAST parser
1 parent 99bd120 commit a3dc848

File tree

4 files changed

+580
-0
lines changed

4 files changed

+580
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package org.owasp.benchmarkutils.score.parsers;
2+
3+
import org.json.JSONArray;
4+
import org.json.JSONObject;
5+
import org.owasp.benchmarkutils.score.*;
6+
7+
public class GitLabSastReader extends Reader {
8+
@Override
9+
public boolean canRead(ResultFile resultFile) {
10+
return resultFile.isJson()
11+
&& resultFile.json().has("scan")
12+
&& resultFile
13+
.json()
14+
.getJSONObject("scan")
15+
.getJSONObject("analyzer")
16+
.getJSONObject("vendor")
17+
.getString("name")
18+
.equalsIgnoreCase("GitLab");
19+
}
20+
21+
@Override
22+
public TestSuiteResults parse(ResultFile resultFile) throws Exception {
23+
TestSuiteResults tr = new TestSuiteResults("GitLab-SAST", true, TestSuiteResults.ToolType.SAST);
24+
25+
JSONArray vulnerabilities = resultFile.json().getJSONArray("vulnerabilities");
26+
27+
for (int vulnerability = 0; vulnerability < vulnerabilities.length(); vulnerability++) {
28+
TestCaseResult tcr = parseGitLabSastFindings(vulnerabilities.getJSONObject(vulnerability));
29+
if (tcr != null) {
30+
tr.put(tcr);
31+
}
32+
}
33+
return tr;
34+
}
35+
36+
private TestCaseResult parseGitLabSastFindings(JSONObject vulnerability) {
37+
38+
try {
39+
String className = vulnerability.getJSONObject("location").getString("file");
40+
className = (className.substring(className.lastIndexOf('/') + 1)).split("\\.")[0];
41+
42+
if (className.startsWith(BenchmarkScore.TESTCASENAME)) {
43+
TestCaseResult tcr = new TestCaseResult();
44+
45+
JSONArray identifiers = vulnerability.getJSONArray("identifiers");
46+
47+
int cwe = identifiers.getJSONObject(1).getInt("value");
48+
cwe = translate(cwe);
49+
50+
String category = identifiers.getJSONObject(2).getString("name");
51+
category = category.split("-")[1].strip();
52+
53+
String evidence = vulnerability.getString("cve");
54+
55+
tcr.setCWE(cwe);
56+
tcr.setCategory(category);
57+
tcr.setEvidence(evidence);
58+
tcr.setConfidence(0);
59+
tcr.setNumber(testNumber(className));
60+
61+
return tcr;
62+
}
63+
} catch (Exception ex) {
64+
ex.printStackTrace();
65+
}
66+
67+
return null;
68+
}
69+
70+
private int translate(int cwe) {
71+
//in gitlab sast {
72+
// "trustbound": 306, // Authentication Bypass Using Trust Boundaries (CWE-306)
73+
// "weakrand": 338, // Use of Cryptographically Weak Pseudo-Random Number Generator (CWE-338)
74+
// "sqli": 89, // SQL Injection (CWE-89)
75+
// "crypto": 327, // Use of a Broken or Risky Cryptographic Algorithm (CWE-327)
76+
// "cmdi": 185, // Improper Control of Generation of Code ('Code Injection') (CWE-185)
77+
// "xss": 79, // Cross-site Scripting (CWE-79)
78+
// "hash": 326, // Inadequate Encryption Strength (CWE-326)
79+
// "pathtraver": 22, // Path Traversal (CWE-22)
80+
// "securecookie": 614, // Sensitive Cookie in HTTPS Session Without 'Secure' Attribute (CWE-614)
81+
// "xpathi": 643, // XPath Injection (CWE-643)
82+
// "ldapi": 90, // Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection') (CWE-90)
83+
// "httpresponse": 113, // Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting') (CWE-113)
84+
// "debugcode": 259, // Use of Hard-coded Password (CWE-259)
85+
// "cryptointegration": 1004 // Sensitive Cookie Without 'HttpOnly' Flag (CWE-1004)
86+
//}
87+
88+
//in benchmark tool {
89+
// "trustbound": 501,
90+
// "weakrand": 330,
91+
// "sqli": 89,
92+
// "crypto": 327,
93+
// "cmdi": 78,
94+
// "xss": 79,
95+
// "hash": 328,
96+
// "pathtraver": 22,
97+
// "securecookie": 614,
98+
// "xpathi": 643,
99+
// "ldapi": 90
100+
//}
101+
switch (cwe) {
102+
case 22:
103+
return CweNumber.PATH_TRAVERSAL;
104+
case 79:
105+
return CweNumber.XSS;
106+
case 89:
107+
return CweNumber.SQL_INJECTION;
108+
case 90:
109+
return CweNumber.LDAP_INJECTION;
110+
case 113:
111+
return CweNumber.HTTP_RESPONSE_SPLITTING;
112+
case 185:
113+
return CweNumber.COMMAND_INJECTION;
114+
case 326:
115+
case 327:
116+
case 328:
117+
return CweNumber.WEAK_CRYPTO_ALGO;
118+
case 338:
119+
return CweNumber.WEAK_RANDOM;
120+
case 614:
121+
return CweNumber.INSECURE_COOKIE;
122+
case 643:
123+
return CweNumber.XPATH_INJECTION;
124+
case 1004:
125+
return CweNumber.COOKIE_WITHOUT_HTTPONLY;
126+
case 259:
127+
case 306:
128+
break;
129+
default:
130+
System.out.println(
131+
"INFO: Found following CWE in GitLab SAST results which we haven't seen before: "
132+
+ cwe);
133+
}
134+
135+
return cwe;
136+
}
137+
}

plugin/src/main/java/org/owasp/benchmarkutils/score/parsers/Reader.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public static List<Reader> allReaders() {
7373
new FluidAttacksReader(),
7474
new FortifyReader(),
7575
new FusionLiteInsightReader(),
76+
new GitLabSastReader(),
7677
new HCLAppScanIASTReader(),
7778
new HCLAppScanSourceReader(),
7879
new HCLAppScanStandardReader(),
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package org.owasp.benchmarkutils.score.parsers;
2+
3+
import org.json.JSONArray;
4+
import org.junit.jupiter.api.BeforeEach;
5+
import org.junit.jupiter.api.Test;
6+
import org.owasp.benchmarkutils.score.*;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertTrue;
10+
11+
class GitLabSastReaderTest extends ReaderTestBase {
12+
13+
private ResultFile resultFile;
14+
15+
@BeforeEach
16+
void setUp() {
17+
resultFile = TestHelper.resultFileOf("testfiles/Benchmark_GitLab_SAST.json");
18+
BenchmarkScore.TESTCASENAME = "BenchmarkTest";
19+
}
20+
21+
@Test
22+
public void onlyGitLabSastReaderReportsCanReadAsTrue() {
23+
assertOnlyMatcherClassIs(this.resultFile, GitLabSastReader.class);
24+
}
25+
26+
@Test
27+
void readerHandlesGivenResultFile() throws Exception {
28+
GitLabSastReader reader = new GitLabSastReader();
29+
TestSuiteResults result = reader.parse(resultFile);
30+
31+
assertEquals(TestSuiteResults.ToolType.SAST, result.getToolType());
32+
assertTrue(result.isCommercial());
33+
assertEquals("GitLab-SAST", result.getToolName());
34+
35+
assertEquals(5, result.getTotalResults());
36+
37+
assertEquals(CweNumber.WEAK_CRYPTO_ALGO, result.get(1).get(0).getCWE());
38+
assertEquals(CweNumber.PATH_TRAVERSAL, result.get(5).get(0).getCWE());
39+
}
40+
41+
@Test
42+
void isAbleToFetchTestFileClassName() {
43+
JSONArray vulnerabilities = resultFile.json().getJSONArray("vulnerabilities");
44+
String path = vulnerabilities.getJSONObject(1).getJSONObject("location").getString("file");
45+
46+
assertEquals("src/main/java/org/owasp/benchmark/testcode/BenchmarkTest00614.java", path);
47+
48+
String className = (path.substring(path.lastIndexOf('/') + 1)).split("\\.")[0];
49+
assertTrue(className.startsWith(BenchmarkScore.TESTCASENAME));
50+
51+
JSONArray identifiers = vulnerabilities.getJSONObject(1).getJSONArray("identifiers");
52+
int cwe = identifiers.getJSONObject(1).getInt("value");
53+
assertEquals(327, cwe);
54+
55+
String category = identifiers.getJSONObject(2).getString("name");
56+
category = category.split("-")[1].strip();
57+
assertEquals("Cryptographic Failures", category);
58+
59+
String evidence = vulnerabilities.getJSONObject(1).getString("cve");
60+
assertEquals("semgrep_id:find_sec_bugs.CIPHER_INTEGRITY-1:71:71", evidence);
61+
}
62+
}

0 commit comments

Comments
 (0)