package output import ( "encoding/xml" htmlLib "html" "strconv" "github.com/securego/gosec" ) type junitXMLReport struct { XMLName xml.Name `xml:"testsuites"` Testsuites []testsuite `xml:"testsuite"` } type testsuite struct { XMLName xml.Name `xml:"testsuite"` Name string `xml:"name,attr"` Tests int `xml:"tests,attr"` Testcases []testcase `xml:"testcase"` } type testcase struct { XMLName xml.Name `xml:"testcase"` Name string `xml:"name,attr"` Failure failure `xml:"failure"` } type failure struct { XMLName xml.Name `xml:"failure"` Message string `xml:"message,attr"` Text string `xml:",innerxml"` } func generatePlaintext(issue *gosec.Issue) string { return "Results:\n" + "[" + issue.File + ":" + issue.Line + "] - " + issue.What + " (Confidence: " + strconv.Itoa(int(issue.Confidence)) + ", Severity: " + strconv.Itoa(int(issue.Severity)) + ", CWE: " + issue.Cwe.ID + ")\n" + "> " + htmlLib.EscapeString(issue.Code) } func groupDataByRules(data *reportInfo) map[string][]*gosec.Issue { groupedData := make(map[string][]*gosec.Issue) for _, issue := range data.Issues { if _, ok := groupedData[issue.What]; ok { groupedData[issue.What] = append(groupedData[issue.What], issue) } else { groupedData[issue.What] = []*gosec.Issue{issue} } } return groupedData } func createJUnitXMLStruct(groupedData map[string][]*gosec.Issue) junitXMLReport { var xmlReport junitXMLReport for what, issues := range groupedData { testsuite := testsuite{ Name: what, Tests: len(issues), } for _, issue := range issues { testcase := testcase{ Name: issue.File, Failure: failure{ Message: "Found 1 vulnerability. See stacktrace for details.", Text: generatePlaintext(issue), }, } testsuite.Testcases = append(testsuite.Testcases, testcase) } xmlReport.Testsuites = append(xmlReport.Testsuites, testsuite) } return xmlReport }