Skip to content

Commit

Permalink
Correctly calculate statistics when running scans (#649)
Browse files Browse the repository at this point in the history
Signed-off-by: egibs <[email protected]>
  • Loading branch information
egibs authored Nov 19, 2024
1 parent caa8692 commit 5855d35
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 25 deletions.
4 changes: 2 additions & 2 deletions pkg/action/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ func recursiveScan(ctx context.Context, c malcontent.Config) (*malcontent.Report
if k, ok := key.(string); ok {
if fr, ok := value.(*malcontent.FileReport); ok {
if len(c.TrimPrefixes) > 0 {
path = report.TrimPrefixes(k, c.TrimPrefixes)
k = report.TrimPrefixes(k, c.TrimPrefixes)
}
r.Files.Store(k, fr)
if c.Renderer != nil && r.Diff == nil && fr.RiskScore >= c.MinFileRisk {
Expand Down Expand Up @@ -562,7 +562,7 @@ func Scan(ctx context.Context, c malcontent.Config) (*malcontent.Report, error)
return true
})
if c.Stats {
err = render.Statistics(r)
err = render.Statistics(&c, r)
if err != nil {
return r, fmt.Errorf("stats: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/render/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func matchFragmentLink(s string) string {
func (r Markdown) Scanning(_ context.Context, _ string) {}

func (r Markdown) File(ctx context.Context, fr *malcontent.FileReport) error {
if len(fr.Behaviors) > 0 {
if fr.Skipped == "" && len(fr.Behaviors) > 0 {
markdownTable(ctx, fr, r.w, tableConfig{Title: fmt.Sprintf("## %s [%s]", fr.Path, mdRisk(fr.RiskScore, fr.RiskLevel))})
}
return nil
Expand Down
44 changes: 28 additions & 16 deletions pkg/render/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,34 @@ func smLength(m *sync.Map) int {
return length
}

func riskStatistics(files *sync.Map) ([]malcontent.IntMetric, int, int) {
func riskStatistics(c *malcontent.Config, files *sync.Map) ([]malcontent.IntMetric, int, int, int) {
length := smLength(files)

riskMap := make(map[int][]string, length)
riskStats := make(map[int]float64, length)

// as opposed to skipped files
processedFiles := 0
skippedFiles := 0
files.Range(func(key, value any) bool {
if key == nil || value == nil {
return true
}
processedFiles++

if fr, ok := value.(*malcontent.FileReport); ok {
if fr.Skipped == "" {
riskMap[fr.RiskScore] = append(riskMap[fr.RiskScore], fr.Path)
switch {
case c.Scan:
if fr.RiskScore >= 3 {
riskMap[fr.RiskScore] = append(riskMap[fr.RiskScore], fr.Path)
} else {
skippedFiles++
}
default:
if fr.Skipped == "" {
riskMap[fr.RiskScore] = append(riskMap[fr.RiskScore], fr.Path)
} else {
skippedFiles++
}
}
}
for riskLevel := range riskMap {
Expand All @@ -52,16 +64,16 @@ func riskStatistics(files *sync.Map) ([]malcontent.IntMetric, int, int) {
return t
}
for k, v := range riskStats {
stats = append(stats, malcontent.IntMetric{Key: k, Value: v, Count: len(riskMap[k]), Total: total()})
stats = append(stats, malcontent.IntMetric{Key: k, Value: v, Count: len(riskMap[k]), Total: processedFiles})
}
sort.Slice(stats, func(i, j int) bool {
return stats[i].Value > stats[j].Value
})

return stats, total(), processedFiles
return stats, total(), processedFiles, skippedFiles
}

func pkgStatistics(files *sync.Map) ([]malcontent.StrMetric, int, int) {
func pkgStatistics(_ *malcontent.Config, files *sync.Map) ([]malcontent.StrMetric, int, int) {
length := smLength(files)
numBehaviors := 0
pkgMap := make(map[string]int, length)
Expand All @@ -71,9 +83,11 @@ func pkgStatistics(files *sync.Map) ([]malcontent.StrMetric, int, int) {
return true
}
if fr, ok := value.(*malcontent.FileReport); ok {
for _, b := range fr.Behaviors {
numBehaviors++
pkgMap[b.ID]++
if fr.Skipped == "" {
for _, b := range fr.Behaviors {
numBehaviors++
pkgMap[b.ID]++
}
}
}
return true
Expand Down Expand Up @@ -102,18 +116,16 @@ func pkgStatistics(files *sync.Map) ([]malcontent.StrMetric, int, int) {
return stats, width, numBehaviors
}

func Statistics(r *malcontent.Report) error {
riskStats, totalRisks, totalFilesProcessed := riskStatistics(&r.Files)
pkgStats, width, totalBehaviors := pkgStatistics(&r.Files)

length := smLength(&r.Files)
func Statistics(c *malcontent.Config, r *malcontent.Report) error {
riskStats, totalRisks, processedFiles, skippedFiles := riskStatistics(c, &r.Files)
pkgStats, width, totalBehaviors := pkgStatistics(c, &r.Files)

statsSymbol := "📊"
riskSymbol := "⚠️ "
pkgSymbol := "📦"
fmt.Printf("%s Statistics\n", statsSymbol)
fmt.Println("---")
fmt.Printf("\033[1;37m%-15s \033[1;37m%s\033[0m\n", "Files Scanned", fmt.Sprintf("%d (%d skipped)", totalFilesProcessed, length-totalFilesProcessed))
fmt.Printf("\033[1;37m%-15s \033[1;37m%s\033[0m\n", "Files Scanned", fmt.Sprintf("%d (%d skipped)", processedFiles, skippedFiles))
fmt.Printf("\033[1;37m%-15s \033[1;37m%s\033[0m\n", "Total Risks", fmt.Sprintf("%d", totalRisks))
fmt.Println("---")
fmt.Printf("%s Risk Level Percentage\n", riskSymbol)
Expand Down
2 changes: 1 addition & 1 deletion pkg/render/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (r StringMatches) Scanning(_ context.Context, path string) {
}

func (r StringMatches) File(_ context.Context, fr *malcontent.FileReport) error {
if len(fr.Behaviors) == 0 {
if fr.Skipped != "" || len(fr.Behaviors) == 0 {
return nil
}

Expand Down
6 changes: 5 additions & 1 deletion pkg/render/terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (r Terminal) Scanning(_ context.Context, path string) {
}

func (r Terminal) File(ctx context.Context, fr *malcontent.FileReport) error {
if len(fr.Behaviors) > 0 {
if fr.Skipped == "" && len(fr.Behaviors) > 0 {
renderFileSummary(ctx, fr, r.w,
tableConfig{
Title: fmt.Sprintf("%s %s", fr.Path, darkBrackets(riskInColor(fr.RiskLevel))),
Expand Down Expand Up @@ -226,6 +226,10 @@ func renderFileSummary(_ context.Context, fr *malcontent.FileReport, w io.Writer
previousNsRiskScore := map[string]int{}
diffMode := false

if fr.Skipped != "" {
return
}

for _, b := range fr.Behaviors {
ns, _ := splitRuleID(b.ID)

Expand Down
2 changes: 1 addition & 1 deletion pkg/render/terminal_brief.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (r TerminalBrief) Scanning(_ context.Context, path string) {
}

func (r TerminalBrief) File(_ context.Context, fr *malcontent.FileReport) error {
if len(fr.Behaviors) == 0 {
if fr.Skipped != "" || len(fr.Behaviors) == 0 {
return nil
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ func Generate(ctx context.Context, path string, mrs yara.MatchRules, c malconten
if c.Scan {
highestRisk = highestMatchRisk(mrs)
if highestRisk < 3 {
return malcontent.FileReport{}, nil
fr.Skipped = "overall risk too low for scan"
}
}

Expand Down Expand Up @@ -592,14 +592,14 @@ func Generate(ctx context.Context, path string, mrs yara.MatchRules, c malconten
}

if c.Scan && overallRiskScore < HIGH {
return malcontent.FileReport{}, nil
fr.Skipped = "overall risk too low for scan"
}

// Check for both the full and shortened variants of malcontent
isMalBinary := (filepath.Base(path) == NAME || filepath.Base(path) == "mal")

if all(ignoreSelf, fr.IsMalcontent, ignoreMalcontent, isMalBinary) {
return malcontent.FileReport{}, nil
fr.Skipped = "ignoring malcontent binary"
}

// If something has a lot of high, it's probably critical
Expand Down

0 comments on commit 5855d35

Please sign in to comment.