Skip to content

Commit

Permalink
feat: gitlab report format
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasfi committed Oct 9, 2023
1 parent 949661b commit e71d434
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,13 @@ public enum Format {
/**
* Generate JUNIT report.
*/
JUNIT
JUNIT,
/**
* Generate Report in GitLab dependency check format:
* @see <a href="https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dependency-scanning-report-format.json">format definition</a>
* @see <a href="https://docs.gitlab.com/ee/development/integrations/secure.html">additional explantions on the format</a>
*/
GITLAB
}

/**
Expand Down Expand Up @@ -251,6 +257,7 @@ private VelocityContext createContext(String applicationName, List<Dependency> d
final String scanDate = DateTimeFormatter.RFC_1123_DATE_TIME.format(dt);
final String scanDateXML = DateTimeFormatter.ISO_INSTANT.format(dt);
final String scanDateJunit = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(dt);
final String scanDateGitLab = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(dt.withNano(0));

final VelocityContext ctxt = new VelocityContext();
ctxt.put("applicationName", applicationName);
Expand All @@ -261,6 +268,7 @@ private VelocityContext createContext(String applicationName, List<Dependency> d
ctxt.put("scanDate", scanDate);
ctxt.put("scanDateXML", scanDateXML);
ctxt.put("scanDateJunit", scanDateJunit);
ctxt.put("scanDateGitLab", scanDateGitLab);
ctxt.put("enc", new EscapeTool());
ctxt.put("rpt", new ReportTool());
ctxt.put("checksum", Checksum.class);
Expand Down Expand Up @@ -394,6 +402,9 @@ public static File getReportFile(String outputLocation, Format format) {
if (format == Format.SARIF && !pathToCheck.endsWith(".sarif")) {
return new File(outFile, "dependency-check-report.sarif");
}
if (format == Format.GITLAB && !pathToCheck.endsWith(".json")) {
return new File(outFile, "dependency-check-gitlab.json");
}
return outFile;
}

Expand Down
137 changes: 137 additions & 0 deletions core/src/main/resources/templates/gitlabReport.vsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{
"version": "15.0.6",
"schema": "https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/raw/v15.0.6/dist/dependency-scanning-report-format.json?ref_type=tags", ##todo
"scan": {
## this describes the tool responsible for scanning
"scanner": {
"id": "org.owasp.dependency-check",
"name": "Dependency-Check Core",
"version": "$enc.json($version)",
"vendor": {
"name": "OWASP"
},

## optional properties
"url": "https://github.com/jeremylong/DependencyCheck/"
},
## this describes the tool responsible for interpreting the scan result
## in our case it's the same as the scanner
"analyzer": {
"id": "org.owasp.dependency-check",
"name": "Dependency-Check Core",
"version": "$enc.json($version)",
"vendor": {
"name": "OWASP"
},

## optional properties
"url": "https://github.com/jeremylong/DependencyCheck/"
},

"end_time": "$enc.json($scanDateGitLab)",
## we don't acutally have the real start time, so this is the best we can do
"start_time": "$enc.json($scanDateGitLab)",
## we only generate a scan report, if the scan has successfully finished
"status": #if($exceptions) "failure" #else "success" #end ,
## this is the only type of scan there is according to the format definition
"type": "dependency_scanning"

## optional properties
## "messages": [], --> not implemented
##"options": [], --> not implemented
##"primary_identifiers": [], --> not implemented
},
"vulnerabilities": [
#set( $vulnerability_first = true )
#foreach( $dependency in $dependencies )
#if( $dependency.vulnerabilities.size() != 0 )
#foreach( $vulnerability in $dependency.getVulnerabilities(true) )
## make sure to insert comma between array elements
#if( $vulnerability_first == true )
#set( $vulnerability_first = false )
#else
,
#end
## ((List<Dependency>)context.get("dependencies")).get(5).getVulnerabilities().stream().collect(Collectors.toList()).get(0)
{
"id": "$enc.json($vulnerability.name)", ##todo
"identifiers": [
#foreach( $ref in $vulnerability.getReferences(true) )
{
"type": "$enc.json($ref.source)",
"name": "$enc.json($ref.name)",
"value": "$enc.json($ref.name)",

## optional properties
"url": "$enc.json($ref.url)"
}
#if( $foreach.hasNext ),#end
#end
],
"location": {
"file": "$enc.json($dependency.filePath)",
"dependency": {
"package": {
"name": "$enc.json($dependency.name)"
},
"version": "$enc.json($dependency.version)"
## optional properties
## "iid": "", --> not implemented
## "direct": false, --> not implemented
## we don't have a good way of assigning iids, so this won't work
##"dependency_path": [
## #foreach( $inc in $dependency.includedBy )
## {
## "iid":
## }
## #if( $foreach.hasNext ),#end
## #end
##]
}
},

## optional properties
"name": "$enc.json($vulnerability.name)",
"description": "$enc.json($vulnerability.description)",
"severity": "$enc.json($vulnerability.cvssV3.getBaseSeverity())",
## we have to include this field to be compliant with the format spec
"solution": "" ## todo: not in our dataset?

## "links": [], --> not implemented
## "details": [], --> not implemented
## "tracking": {}, --> not implemented
## "flags": [], --> not implemented.
}
#end
#end
#end
],
"dependency_files": [
## for lack of better knowledge, we just assume we have only scanned a single pom.xml file…
{
"path": "pom.xml",
"package_manager": "maven",
"dependencies": [
#foreach( $dependency in $dependencies )
{
"package": {
"name": "$enc.json($dependency.name)"
},
"version": "$enc.json($dependency.version)"

## optional properties
## "iid": number, --> not implemtend
##"direct": false, --> not implemeten
##"dependency_path": [] --> not implemented
}
#if( $foreach.hasNext ),#end
#end
]
## no optional properties
}
],

## optional properties
"remediations": [], ## not implemented

}

0 comments on commit e71d434

Please sign in to comment.