/
writer.go
115 lines (103 loc) · 2.55 KB
/
writer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package text
import (
"bufio"
"bytes"
_ "embed" // use go embed to import template
"fmt"
"io"
"strconv"
"strings"
"text/template"
"github.com/gookit/color"
"github.com/securego/gosec/v2"
"github.com/securego/gosec/v2/issue"
)
var (
errorTheme = color.New(color.FgLightWhite, color.BgRed)
warningTheme = color.New(color.FgBlack, color.BgYellow)
defaultTheme = color.New(color.FgWhite, color.BgBlack)
//go:embed template.txt
templateContent string
)
// WriteReport write a (colorized) report in text format
func WriteReport(w io.Writer, data *gosec.ReportInfo, enableColor bool) error {
t, e := template.
New("gosec").
Funcs(plainTextFuncMap(enableColor)).
Parse(templateContent)
if e != nil {
return e
}
return t.Execute(w, data)
}
func plainTextFuncMap(enableColor bool) template.FuncMap {
if enableColor {
return template.FuncMap{
"highlight": highlight,
"danger": color.Danger.Render,
"notice": color.Notice.Render,
"success": color.Success.Render,
"printCode": printCodeSnippet,
}
}
// by default those functions return the given content untouched
return template.FuncMap{
"highlight": func(t string, s issue.Score, ignored bool) string {
return t
},
"danger": fmt.Sprint,
"notice": fmt.Sprint,
"success": fmt.Sprint,
"printCode": printCodeSnippet,
}
}
// highlight returns content t colored based on Score
func highlight(t string, s issue.Score, ignored bool) string {
if ignored {
return defaultTheme.Sprint(t)
}
switch s {
case issue.High:
return errorTheme.Sprint(t)
case issue.Medium:
return warningTheme.Sprint(t)
default:
return defaultTheme.Sprint(t)
}
}
// printCodeSnippet prints the code snippet from the issue by adding a marker to the affected line
func printCodeSnippet(issue *issue.Issue) string {
start, end := parseLine(issue.Line)
scanner := bufio.NewScanner(strings.NewReader(issue.Code))
var buf bytes.Buffer
line := start
for scanner.Scan() {
codeLine := scanner.Text()
if strings.HasPrefix(codeLine, strconv.Itoa(line)) && line <= end {
codeLine = " > " + codeLine + "\n"
line++
} else {
codeLine = " " + codeLine + "\n"
}
buf.WriteString(codeLine)
}
return buf.String()
}
// parseLine extract the start and the end line numbers from a issue line
func parseLine(line string) (int, int) {
parts := strings.Split(line, "-")
start := parts[0]
end := start
if len(parts) > 1 {
end = parts[1]
}
s, err := strconv.Atoi(start)
if err != nil {
return -1, -1
}
e, err := strconv.Atoi(end)
if err != nil {
return -1, -1
}
return s, e
}