/* Package cmd Copyright © 2024 Shane C. */ package cmd import ( "fmt" "github.com/go-git/go-git/v5" "github.com/kr/pretty" "github.com/nao1215/markdown" "github.com/owenrumney/go-sarif/sarif" "github.com/sethvargo/go-githubactions" "log" "os" "strconv" "strings" "github.com/spf13/cobra" ) var isAction bool var isGithub bool // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "goscan", Short: "A brief description of your application", Run: func(cmd *cobra.Command, args []string) { action := githubactions.New() cwd, err := os.Getwd() if err != nil { log.Fatalln(err) } repo, err := git.PlainOpen(cwd) if err != nil { log.Fatalln(err) } ref, err := repo.Head() if err != nil { log.Fatalln(err) } pretty.Logln(ref.Name().Short()) pretty.Logln(ref.Hash().String()) report, err := sarif.Open("output.sarif") if err != nil { log.Fatal(err) } if len(report.Runs) != 1 { log.Fatalf("expected 1 result, got %d", len(report.Runs)) } run := report.Runs[0] var rows [][]string sevCountMap := map[string]int{ "high": 0, "medium": 0, "low": 0, } for _, result := range run.Results { rule, err := run.GetRuleById(*result.RuleID) if err != nil { log.Fatal(err) } if len(result.Locations) != 1 { log.Fatalf("expected 1 result, got %d", len(result.Locations)) } location := result.Locations[0] severity := rule.Properties["tags"].([]interface{})[1].(string) confidence := rule.Properties["precision"].(string) var severityEmoji string switch strings.ToLower(severity) { case "low": sevCountMap["low"] = sevCountMap["low"] + 1 severityEmoji = "🟨" case "medium": sevCountMap["medium"] = sevCountMap["medium"] + 1 severityEmoji = "🟧" case "high": sevCountMap["high"] = sevCountMap["high"] + 1 severityEmoji = "🟥" } var confidenceEmoji string switch strings.ToLower(confidence) { case "low": confidenceEmoji = "🟧" case "medium": confidenceEmoji = "🟨" case "high": confidenceEmoji = "🟩" } var linkToFile strings.Builder if isGithub { linkToFile.WriteString("./blob/commit/") } else { linkToFile.WriteString("./src/commit/") } linkToFile.WriteString(ref.Hash().String() + "/" + *location.PhysicalLocation.ArtifactLocation.URI + "#L" + strconv.Itoa(*location.PhysicalLocation.Region.StartLine)) rows = append(rows, []string{ fmt.Sprintf("`%s` - %s", *result.RuleID, *rule.Name), fmt.Sprintf("%s **%c**", severityEmoji, severity[0]), fmt.Sprintf("%s **%s**", confidenceEmoji, strings.ToUpper(string(confidence[0]))), fmt.Sprintf("[%s:%d](%s)", *location.PhysicalLocation.ArtifactLocation.URI, *location.PhysicalLocation.Region.StartLine, linkToFile.String()), }) } var markdownOutput strings.Builder markdownHandler := markdown.NewMarkdown(&markdownOutput) markdownHandler.H1("GoSec Results:") markdownHandler.PlainText("
") markdownHandler.PlainText("Results:\n") if len(rows) == 0 { markdownHandler.PlainText("**Nothing Found! 🥳**") } else { if sevCountMap["high"] != 0 { markdownHandler.PlainText(fmt.Sprintf("🟥 **%d** high severity issues\n", sevCountMap["high"])) } if sevCountMap["medium"] != 0 { markdownHandler.PlainText(fmt.Sprintf("🟧 **%d** medium severity issues\n", sevCountMap["medium"])) } if sevCountMap["low"] != 0 { markdownHandler.PlainText(fmt.Sprintf("🟨 **%d** low severity issues\n", sevCountMap["low"])) } markdownHandler.PlainTextf("Total of **%d** issues.\n", sevCountMap["high"]+sevCountMap["medium"]+sevCountMap["low"]) } if len(rows) != 0 { markdownHandler.CustomTable(markdown.TableSet{ Header: []string{"Rule", "Severity", "Confidence", "Location"}, Rows: rows, }, markdown.TableOptions{ AutoWrapText: false, AutoFormatHeaders: false, }) } markdownHandler.PlainText("
") err = markdownHandler.Build() if err != nil { log.Fatalln(err) } action.AddStepSummary(markdownOutput.String()) }, } // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { err := rootCmd.Execute() if err != nil { os.Exit(1) } } func init() { rootCmd.Flags().BoolVar(&isAction, "is-action", false, "If set, will run some things specific to git actions") rootCmd.Flags().BoolVar(&isGithub, "is-github", false, "If set, will change some outputs to support github") }