Skip to content

Commit

Permalink
scan: wolfictl inspired output presentation (#492)
Browse files Browse the repository at this point in the history
* pip: add known good list

* scan: wolfictl inspired output presentation

* shorten empty Scanning commands

---------

Signed-off-by: Thomas Strömberg <[email protected]>
  • Loading branch information
tstromberg authored Oct 7, 2024
1 parent d47acff commit 9729941
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 33 deletions.
10 changes: 5 additions & 5 deletions cmd/mal/mal.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ func main() {
processPaths, err := action.GetAllProcessPaths(ctx)
if err != nil {
returnCode = ExitActionFailed
return err
return fmt.Errorf("process paths: %w", err)
}
for _, p := range processPaths {
mc.ScanPaths = append(mc.ScanPaths, p.Path)
Expand All @@ -394,7 +394,7 @@ func main() {
res, err = action.Scan(ctx, mc)
if err != nil {
returnCode = ExitActionFailed
return err
return fmt.Errorf("scan: %w", err)
}

err = renderer.Full(ctx, res)
Expand Down Expand Up @@ -461,7 +461,7 @@ func main() {
processPaths, err := action.GetAllProcessPaths(ctx)
if err != nil {
returnCode = ExitActionFailed
return err
return fmt.Errorf("process paths: %w", err)
}
for _, p := range processPaths {
mc.ScanPaths = append(mc.ScanPaths, p.Path)
Expand All @@ -471,7 +471,7 @@ func main() {
res, err = action.Scan(ctx, mc)
if err != nil {
returnCode = ExitActionFailed
return err
return fmt.Errorf("scan: %w", err)
}

err = renderer.Full(ctx, res)
Expand All @@ -481,7 +481,7 @@ func main() {
}

if res.Files.Len() > 0 {
fmt.Fprintf(os.Stderr, "\ntip: For detailed analysis, run: mal analyze <path>\n")
fmt.Fprintf(os.Stderr, "\n💡 For detailed analysis, try \"mal analyze <path>\"\n")
}

return nil
Expand Down
1 change: 1 addition & 0 deletions pkg/action/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ func recursiveScan(ctx context.Context, c malcontent.Config) (*malcontent.Report
var scanPathFindings sync.Map

for _, scanPath := range c.ScanPaths {
c.Renderer.Scanning(ctx, scanPath)
logger.Debug("recursive scan", slog.Any("scanPath", scanPath))
imageURI := ""
ociExtractPath := ""
Expand Down
1 change: 1 addition & 0 deletions pkg/malcontent/malcontent.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

// Renderer is a common interface for Renderers.
type Renderer interface {
Scanning(context.Context, string)
File(context.Context, *FileReport) error
Full(context.Context, *Report) error
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/render/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func NewJSON(w io.Writer) JSON {
return JSON{w: w}
}

func (r JSON) Scanning(_ context.Context, _ string) {}

func (r JSON) File(_ context.Context, _ *malcontent.FileReport) error {
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/render/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func matchFragmentLink(s string) string {
return fmt.Sprintf("[%s](https://github.com/search?q=%s&type=code)", s, url.QueryEscape(s))
}

func (r Markdown) Scanning(_ context.Context, _ string) {}

func (r Markdown) File(ctx context.Context, fr *malcontent.FileReport) error {
if len(fr.Behaviors) > 0 {
markdownTable(ctx, fr, r.w, tableConfig{Title: fmt.Sprintf("## %s [%s]", fr.Path, mdRisk(fr.RiskScore, fr.RiskLevel))})
Expand Down
2 changes: 2 additions & 0 deletions pkg/render/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func NewSimple(w io.Writer) Simple {
return Simple{w: w}
}

func (r Simple) Scanning(_ context.Context, _ string) {}

func (r Simple) File(_ context.Context, fr *malcontent.FileReport) error {
if fr.Skipped != "" {
return nil
Expand Down
19 changes: 19 additions & 0 deletions pkg/render/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ var riskLevels = map[int]string{
4: "CRITICAL", // critical: certainly malware
}

func briefRiskColor(level string) string {
switch level {
case "LOW":
return color.HiGreenString("LOW")
case "MEDIUM", "MED":
return color.HiYellowString("MED")
case "HIGH":
return color.HiRedString("HIGH")
case "CRITICAL", "CRIT":
return color.HiMagentaString("CRIT")
default:
return color.WhiteString(level)
}
}

type StringMatches struct {
w io.Writer
}
Expand All @@ -58,6 +73,10 @@ type Match struct {
Strings []string
}

func (r StringMatches) Scanning(_ context.Context, path string) {
fmt.Fprintf(r.w, "🔎 Scanning %q\n", path)
}

func (r StringMatches) File(_ context.Context, fr *malcontent.FileReport) error {
if len(fr.Behaviors) == 0 {
return nil
Expand Down
28 changes: 18 additions & 10 deletions pkg/render/terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,29 @@ func NewTerminal(w io.Writer) Terminal {
}

func decorativeRisk(score int, level string) string {
return fmt.Sprintf("%s %s", riskEmoji(score), riskColor(level))
return fmt.Sprintf("%s %s", riskEmoji(score), riskColor(level, level))
}

func darkBrackets(s string) string {
return fmt.Sprintf("%s%s%s", color.HiBlackString("["), s, color.HiBlackString("]"))
}

func riskColor(level string) string {
func riskInColor(level string) string {
return riskColor(level, level)
}

func riskColor(level string, text string) string {
switch level {
case "LOW":
return color.HiGreenString(level)
return color.HiGreenString(text)
case "MEDIUM", "MED":
return color.HiYellowString(level)
return color.HiYellowString(text)
case "HIGH":
return color.HiRedString(level)
return color.HiRedString(text)
case "CRITICAL", "CRIT":
return color.HiMagentaString(level)
return color.HiMagentaString(text)
default:
return color.WhiteString(level)
return color.WhiteString(text)
}
}

Expand All @@ -90,6 +94,10 @@ func ShortRisk(s string) string {
return short
}

func (r Terminal) Scanning(_ context.Context, path string) {
fmt.Fprintf(r.w, "🔎 Scanning %q\n", path)
}

func (r Terminal) File(ctx context.Context, fr *malcontent.FileReport) error {
if len(fr.Behaviors) > 0 {
renderTable(ctx, fr, r.w,
Expand Down Expand Up @@ -279,12 +287,12 @@ func renderTable(ctx context.Context, fr *malcontent.FileReport, w io.Writer, rc
}
evidence := strings.Join(abbreviatedEv, "\n")

risk := riskColor(ShortRisk(k.Behavior.RiskLevel))
risk := riskInColor(ShortRisk(k.Behavior.RiskLevel))
if k.Behavior.DiffAdded || rc.DiffAdded {
if rc.SkipAdded {
continue
}
risk = fmt.Sprintf("%s%s", color.HiWhiteString("+"), riskColor(ShortRisk(k.Behavior.RiskLevel)))
risk = fmt.Sprintf("%s%s", color.HiWhiteString("+"), riskInColor(ShortRisk(k.Behavior.RiskLevel)))
}

wKey := wrapKey(k.Key, keyWidth)
Expand All @@ -294,7 +302,7 @@ func renderTable(ctx context.Context, fr *malcontent.FileReport, w io.Writer, rc
if rc.SkipRemoved {
continue
}
risk = fmt.Sprintf("%s%s", color.WhiteString("-"), riskColor(ShortRisk(k.Behavior.RiskLevel)))
risk = fmt.Sprintf("%s%s", color.WhiteString("-"), riskInColor(ShortRisk(k.Behavior.RiskLevel)))
evidence = darkenText(evidence)
}

Expand Down
23 changes: 5 additions & 18 deletions pkg/render/terminal_brief.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"context"
"fmt"
"io"
"strings"

"github.com/chainguard-dev/malcontent/pkg/malcontent"
"github.com/fatih/color"
Expand All @@ -29,33 +28,21 @@ func NewTerminalBrief(w io.Writer) TerminalBrief {
return TerminalBrief{w: w}
}

func briefRiskColor(level string) string {
switch level {
case "LOW":
return color.HiGreenString("LOW")
case "MEDIUM", "MED":
return color.HiYellowString("MED")
case "HIGH":
return color.HiRedString("HIGH")
case "CRITICAL", "CRIT":
return color.HiMagentaString("CRIT")
default:
return color.WhiteString(level)
}
func (r TerminalBrief) Scanning(_ context.Context, path string) {
fmt.Fprintf(r.w, "🔎 Scanning %q\n", path)
}

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

reasons := []string{}
fmt.Fprintf(r.w, "├── 📄 %s %s%s%s\n", fr.Path, color.HiBlackString("["), riskInColor(fr.RiskLevel), color.HiBlackString("]"))

for _, b := range fr.Behaviors {
reasons = append(reasons, fmt.Sprintf("%s %s%s%s\n", color.HiYellowString(b.ID), color.HiBlackString("("), b.Description, color.HiBlackString(")")))
fmt.Fprintf(r.w, "│ %s %s: %s\n", riskEmoji(fr.RiskScore), riskColor(fr.RiskLevel, b.ID), b.Description)
}

fmt.Fprintf(r.w, "%s%s%s %s: \n%s%s\n", color.HiBlackString("["), briefRiskColor(fr.RiskLevel), color.HiBlackString("]"), color.HiGreenString(fr.Path),
color.HiBlackString("- "), strings.Join(reasons, color.HiBlackString("- ")))
return nil
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/render/yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func NewYAML(w io.Writer) YAML {
return YAML{w: w}
}

func (r YAML) Scanning(_ context.Context, _ string) {}

func (r YAML) File(_ context.Context, _ *malcontent.FileReport) error {
return nil
}
Expand Down

0 comments on commit 9729941

Please sign in to comment.