Skip to content

Commit

Permalink
Add separate analyze command for displaying all rule matches
Browse files Browse the repository at this point in the history
Signed-off-by: egibs <[email protected]>
  • Loading branch information
egibs committed Sep 10, 2024
1 parent d3bc716 commit e7eb3bd
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
56 changes: 55 additions & 1 deletion bincapz.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ var (
outputFlag string
profileFlag bool
quantityIncreasesRiskFlag bool
scanFlag bool
statsFlag bool
thirdPartyFlag bool
verboseFlag bool
Expand Down Expand Up @@ -314,6 +315,12 @@ func main() {
Usage: "Increase file risk score based on behavior quantity",
Destination: &quantityIncreasesRiskFlag,
},
&cli.BoolFlag{
Name: "scan",
Value: false,
Usage: "Only return findings matching the highest severity",
Destination: &scanFlag,
},
&cli.BoolFlag{
Name: "stats",
Aliases: []string{"s"},
Expand All @@ -335,6 +342,52 @@ func main() {
},
},
Commands: []*cli.Command{
{
Name: "analyze",
Usage: "fully interrogate a path",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "image",
Aliases: []string{"i"},
Value: "",
Usage: "Scan an image",
},
&cli.StringFlag{
Name: "path",
Aliases: []string{"p"},
Value: "",
Usage: "Scan a file path",
},
},
Action: func(c *cli.Context) error {
// Handle edge cases
// Set bc.OCI if the image flag is used
// Default to path scanning if neither flag is passed (images must be scanned via --image or -i)
switch {
case c.String("image") != "":
bc.OCI = true
case c.String("image") == "" || c.String("path") == "":
cmdArgs := c.Args().Slice()
bc.ScanPaths = []string{cmdArgs[0]}
}

res, err = action.Scan(ctx, bc)
if err != nil {
log.Error("scan failed", slog.Any("error", err))
returnCode = ExitActionFailed
return err
}

err = renderer.Full(ctx, res)
if err != nil {
log.Error("render failed", slog.Any("error", err))
returnCode = ExitRenderFailed
return err
}

return nil
},
},
{
Name: "diff",
Usage: "scan and diff two paths",
Expand All @@ -357,7 +410,7 @@ func main() {
},
{
Name: "scan",
Usage: "scan an image or path",
Usage: "tersely scan a path and return findings of the highest severity",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "image",
Expand All @@ -373,6 +426,7 @@ func main() {
},
},
Action: func(c *cli.Context) error {
bc.Scan = true
// Handle edge cases
// Set bc.OCI if the image flag is used
// Default to path scanning if neither flag is passed (images must be scanned via --image or -i)
Expand Down
1 change: 1 addition & 0 deletions pkg/bincapz/bincapz.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Config struct {
QuantityIncreasesRisk bool
Renderer Renderer
Rules *yara.Rules
Scan bool
ScanPaths []string
Stats bool
}
Expand Down
29 changes: 28 additions & 1 deletion pkg/report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,12 @@ func Generate(ctx context.Context, path string, mrs yara.MatchRules, c bincapz.C
risk := 0
key := ""

// If we're running a scan, only diplay findings of the highest severity
var highestRisk int
if c.Scan {
highestRisk = highestMatchRisk(mrs)
}

for _, m := range mrs {
if all(m.Rule == BINARY, ignoreSelf) {
ignoreBincapz = true
Expand All @@ -342,7 +348,12 @@ func Generate(ctx context.Context, path string, mrs yara.MatchRules, c bincapz.C
riskCounts[risk]++
// The bincapz rule is classified as harmless
// This will prevent the rule from being filtered
if risk < minScore && !ignoreBincapz {
// If running a scan as opposed to an analyze,
// drop any matches that fall below the highest severity
switch {
case risk < minScore && !ignoreBincapz:
continue
case c.Scan && risk < highestRisk:
continue
}
key = generateKey(m.Namespace, m.Rule)
Expand Down Expand Up @@ -535,3 +546,19 @@ func all(conditions ...bool) bool {
}
return true
}

// highestMatchRisk returns the highest risk score from a slice of MatchRules

Check failure on line 550 in pkg/report/report.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Comment should end in a period (godot)
func highestMatchRisk(mrs yara.MatchRules) int {
if len(mrs) == 0 {
return 0
}

highestRisk := 0
for _, m := range mrs {
risk := behaviorRisk(m.Namespace, m.Rule, m.Tags)
if risk > highestRisk {
highestRisk = risk
}
}
return highestRisk
}

0 comments on commit e7eb3bd

Please sign in to comment.