github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/report/table/secret.go (about) 1 package table 2 3 import ( 4 "bytes" 5 "fmt" 6 "strings" 7 8 "golang.org/x/term" 9 10 "github.com/aquasecurity/tml" 11 dbTypes "github.com/aquasecurity/trivy-db/pkg/types" 12 "github.com/devseccon/trivy/pkg/fanal/types" 13 ) 14 15 type secretRenderer struct { 16 w *bytes.Buffer 17 target string 18 secrets []types.SecretFinding 19 severities []dbTypes.Severity 20 width int 21 ansi bool 22 } 23 24 func NewSecretRenderer(target string, secrets []types.SecretFinding, ansi bool, severities []dbTypes.Severity) *secretRenderer { 25 width, _, err := term.GetSize(0) 26 if err != nil || width == 0 { 27 width = 40 28 } 29 if !ansi { 30 tml.DisableFormatting() 31 } 32 return &secretRenderer{ 33 w: bytes.NewBuffer([]byte{}), 34 target: target, 35 secrets: secrets, 36 severities: severities, 37 width: width, 38 ansi: ansi, 39 } 40 } 41 42 func (r *secretRenderer) Render() string { 43 target := r.target + " (secrets)" 44 RenderTarget(r.w, target, r.ansi) 45 46 severityCount := r.countSeverities() 47 total, summaries := summarize(r.severities, severityCount) 48 49 r.printf("Total: %d (%s)\n\n", total, strings.Join(summaries, ", ")) 50 51 for _, m := range r.secrets { 52 r.renderSingle(m) 53 } 54 return r.w.String() 55 } 56 57 func (r *secretRenderer) countSeverities() map[string]int { 58 severityCount := make(map[string]int) 59 for _, secret := range r.secrets { 60 severity := secret.Severity 61 severityCount[severity]++ 62 } 63 return severityCount 64 } 65 66 func (r *secretRenderer) printf(format string, args ...interface{}) { 67 // nolint 68 _ = tml.Fprintf(r.w, format, args...) 69 } 70 71 func (r *secretRenderer) printDoubleDivider() { 72 r.printf("<dim>%s\r\n", strings.Repeat("═", r.width)) 73 } 74 75 func (r *secretRenderer) printSingleDivider() { 76 r.printf("<dim>%s\r\n", strings.Repeat("─", r.width)) 77 } 78 79 func (r *secretRenderer) renderSingle(secret types.SecretFinding) { 80 r.renderSummary(secret) 81 r.renderCode(secret) 82 r.printf("\r\n\r\n") 83 } 84 85 func (r *secretRenderer) renderSummary(secret types.SecretFinding) { 86 87 // severity 88 switch secret.Severity { 89 case severityCritical: 90 r.printf("<red><bold>%s: ", secret.Severity) 91 case severityHigh: 92 r.printf("<red>%s: ", secret.Severity) 93 case severityMedium: 94 r.printf("<yellow>%s: ", secret.Severity) 95 case severityLow: 96 r.printf("%s: ", secret.Severity) 97 default: 98 r.printf("<blue>%s: ", secret.Severity) 99 } 100 101 // heading 102 r.printf("%s (%s)\r\n", secret.Category, secret.RuleID) 103 r.printDoubleDivider() 104 105 // description 106 r.printf("<dim>%s\r\n", secret.Title) 107 108 r.printSingleDivider() 109 } 110 111 func (r *secretRenderer) renderCode(secret types.SecretFinding) { 112 // highlight code if we can... 113 if lines := secret.Code.Lines; len(lines) > 0 { 114 115 var lineInfo string 116 if secret.StartLine > 0 { 117 lineInfo = tml.Sprintf("<dim>:</dim><blue>%d", secret.StartLine) 118 if secret.EndLine > secret.StartLine { 119 lineInfo = tml.Sprintf("%s<blue>-%d", lineInfo, secret.EndLine) 120 } 121 } 122 123 var note string 124 if c := secret.Layer.CreatedBy; c != "" { 125 if len(c) > 40 { 126 // Too long 127 c = c[:40] 128 } 129 note = fmt.Sprintf(" (added by '%s')", c) 130 } else if secret.Layer.DiffID != "" { 131 note = fmt.Sprintf(" (added in layer '%s')", strings.TrimPrefix(secret.Layer.DiffID, "sha256:")[:12]) 132 } 133 r.printf(" <blue>%s%s<magenta>%s\r\n", r.target, lineInfo, note) 134 r.printSingleDivider() 135 136 for i, line := range lines { 137 switch { 138 case line.Truncated: 139 r.printf("<dim>%4s ", strings.Repeat(".", len(fmt.Sprintf("%d", line.Number)))) 140 case line.IsCause: 141 r.printf("<red>%4d ", line.Number) 142 switch { 143 case (line.FirstCause && line.LastCause) || len(lines) == 1: 144 r.printf("<red>[ ") 145 case line.FirstCause || i == 0: 146 r.printf("<red>┌ ") 147 case line.LastCause || i == len(lines)-1: 148 r.printf("<red>└ ") 149 default: 150 r.printf("<red>│ ") 151 } 152 default: 153 r.printf("<dim>%4d ", line.Number) 154 } 155 if r.ansi { 156 r.printf("%s\r\n", line.Highlighted) 157 } else { 158 r.printf("%s\r\n", line.Content) 159 } 160 } 161 r.printSingleDivider() 162 } 163 }