Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package gokart for openSUSE:Factory checked 
in at 2021-10-11 15:31:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gokart (Old)
 and      /work/SRC/openSUSE:Factory/.gokart.new.2443 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gokart"

Mon Oct 11 15:31:27 2021 rev:3 rq:924309 version:0.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/gokart/gokart.changes    2021-09-14 
21:14:25.780407387 +0200
+++ /work/SRC/openSUSE:Factory/.gokart.new.2443/gokart.changes  2021-10-11 
15:32:23.070918773 +0200
@@ -1,0 +2,20 @@
+Fri Oct 08 14:05:36 UTC 2021 - alexandre.vice...@suse.com
+
+- Update to version 0.3.0:
+  * Enhancements
+    * Output findings to file CLI flag
+    * Verbose output source parent function fix
+    * Add exit code on findings flag
+    * Update remote scanning functionality to include private repos
+    * Add basic dockerfile and README
+    * CWE mappings for findings
+    * Output total findings information
+    * Output findings as json
+    * Highlight relevant finding lines
+  * Bug Fixes
+    * Channel incorrectly identified as source of untrusted input
+    * Verbose trace has incorrect parent signatures
+    * panic: err: go command required
+    * panic: index out of range
+
+-------------------------------------------------------------------
@@ -5,9 +25,3 @@
-  * Add new flags usage to Getting Started (#31)
-  * Adding -r flag to automatically clone and test remote go modules, along 
with functionality to test the Scan cmd (#20)
-  * Making a minor change to error messages when packages aren't found in the 
directory (#28)
-  * Feature enhancement implementation for Issue #3 (Findings Output to File 
Flag) (#24)
-  * changed panic to log.Fatal (#22)
-  * removed non-user-controllable input sources (#23)
-  * typo fixes (#14)
-  * Improved config mgmt and fixed out of bounds panic (#5)
-  * add link to Praetorian blog post in README
+  * Added support for writing findings output to a file to ease CI/CD 
integration via the -o flag.
+  * Added remote fetch + scan functionality via the -r flag.
+  * Updated README to cover new functionality.

Old:
----
  gokart-0.2.0.tar.gz

New:
----
  gokart-0.3.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ gokart.spec ++++++
--- /var/tmp/diff_new_pack.i91Tll/_old  2021-10-11 15:32:23.758919876 +0200
+++ /var/tmp/diff_new_pack.i91Tll/_new  2021-10-11 15:32:23.762919883 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           gokart
-Version:        0.2.0
+Version:        0.3.0
 Release:        0
 Summary:        Static analysis tool for securing Go code
 License:        Apache-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.i91Tll/_old  2021-10-11 15:32:23.786919921 +0200
+++ /var/tmp/diff_new_pack.i91Tll/_new  2021-10-11 15:32:23.786919921 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/praetorian-inc/gokart.git</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v0.2.0</param>
+    <param name="revision">v0.3.0</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
     <param name="versionrewrite-pattern">v(.*)</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.i91Tll/_old  2021-10-11 15:32:23.802919947 +0200
+++ /var/tmp/diff_new_pack.i91Tll/_new  2021-10-11 15:32:23.802919947 +0200
@@ -1,4 +1,4 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/praetorian-inc/gokart.git</param>
-              <param 
name="changesrevision">fecb3b0f40927e14053bbb6dfbce3160e8b388bb</param></service></servicedata>
\ No newline at end of file
+              <param 
name="changesrevision">bb678c03b385071f6a160bd8baed0dacf399165e</param></service></servicedata>
\ No newline at end of file

++++++ gokart-0.2.0.tar.gz -> gokart-0.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/Dockerfile new/gokart-0.3.0/Dockerfile
--- old/gokart-0.2.0/Dockerfile 1970-01-01 01:00:00.000000000 +0100
+++ new/gokart-0.3.0/Dockerfile 2021-09-20 23:52:51.000000000 +0200
@@ -0,0 +1,8 @@
+# syntax=docker/dockerfile:1
+
+FROM golang:1.16-alpine
+WORKDIR /app
+COPY . /app/
+RUN go build -o /gokart
+
+ENTRYPOINT [ "/gokart" ]
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/README.md new/gokart-0.3.0/README.md
--- old/gokart-0.2.0/README.md  2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/README.md  2021-09-20 23:52:51.000000000 +0200
@@ -83,6 +83,25 @@
 $ mv ./gokart /usr/local/bin
 ```
 
+### Docker Support
+Build the docker image
+```shell
+docker build -t gokart .
+```
+
+Running the container with a local scan (the local scan directory needs to be 
mounted to the container image)
+```shell
+docker run -v /path/to/scan-dir:/scan-dir gokart scan /scan-dir
+```
+
+Running the container with a remote scan (when specifying a private key for 
auth, that will also need to be mounted to the container)
+```shell
+docker run gokart scan -r https://github.com/praetorian-inc/gokart
+
+# specifying a private key for private repository ssh authentication
+docker run -v /path/to/key-dir/:/key-dir gokart scan -r 
g...@github.com:praetorian-inc/gokart.git -k /key-dir/ssh_key
+```
+
 ## Usage
 
 ### Run GoKart on a Go module in the current directory
@@ -141,15 +160,24 @@
 # Output scarif results to file
 gokart scan go-test-bench/ -o gokart-go-test-bench.txt -s
 
-# Scan remote repository (private repos require proper authentication)
+# Scan remote public repository 
 # Repository will be cloned locally, scanned and deleted afterwards
-gokart scan -r github.com/ShiftLeftSecurity/shiftleft-go-demo -v
+gokart scan -r https://github.com/ShiftLeftSecurity/shiftleft-go-demo -v
+
+# Specify the remote branch to scan
+gokart scan -r https://github.com/ShiftLeftSecurity/shiftleft-go-demo -b 
actions_fix
+
+# Scan remote private repository via ssh
+gokart scan -r g...@github.com:Contrast-Security-OSS/go-test-bench.git 
+
+# Scan remote private repository and optionally specify a key for ssh 
authentication 
+gokart scan -r g...@github.com:Contrast-Security-OSS/go-test-bench.git -k 
/home/gokart/.ssh/github_rsa_key
 
 # Use remote scan and output flags together for seamless security reviews
-gokart scan -r github.com/ShiftLeftSecurity/shiftleft-go-demo -o 
gokart-shiftleft-go-demo.txt -v 
+gokart scan -r https://github.com/ShiftLeftSecurity/shiftleft-go-demo -o 
gokart-shiftleft-go-demo.txt -v 
 
 # Use remote scan, output and sarif flags for frictionless integration into 
CI/CD
-gokart scan -r github.com/ShiftLeftSecurity/shiftleft-go-demo -o 
gokart-shiftleft-go-demo.txt -s
+gokart scan -r https://github.com/ShiftLeftSecurity/shiftleft-go-demo -o 
gokart-shiftleft-go-demo.txt -s
 ```
 
 To test out the extensibility of GoKart, you can modify the configuration file 
that GoKart uses to
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/cmdi.go 
new/gokart-0.3.0/analyzers/cmdi.go
--- old/gokart-0.2.0/analyzers/cmdi.go  2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/analyzers/cmdi.go  2021-09-20 23:52:51.000000000 +0200
@@ -75,7 +75,7 @@
                                                message := "Danger: possible 
command injection detected"
                                                targetFunc := 
util.GenerateTaintedCode(pass, vulnFunc.Fn, vulnFunc.Instr.Pos())
                                                taintSource := 
taintAnalyzer.TaintSource
-                                               finding := 
util.MakeFinding(message, targetFunc, taintSource, "Command Injection")
+                                               finding := 
util.MakeFinding(message, targetFunc, taintSource, "CWE-78: OS Command 
Injection")
                                                results = append(results, 
finding)
                                        }
                                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/cmdi_test.go 
new/gokart-0.3.0/analyzers/cmdi_test.go
--- old/gokart-0.2.0/analyzers/cmdi_test.go     2021-08-27 20:22:38.000000000 
+0200
+++ new/gokart-0.3.0/analyzers/cmdi_test.go     2021-09-20 23:52:51.000000000 
+0200
@@ -39,7 +39,7 @@
        }
        for i := 0; i < len(testFiles); i++ {
                t.Run(testFiles[i], func(t *testing.T) {
-                       testutil.RunTest(testFiles[i], testResults[i], "Command 
Injection", CommandInjectionAnalyzer, t)
+                       testutil.RunTest(testFiles[i], testResults[i], "CWE-78: 
OS Command Injection", CommandInjectionAnalyzer, t)
                })
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/rsa.go 
new/gokart-0.3.0/analyzers/rsa.go
--- old/gokart-0.2.0/analyzers/rsa.go   2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/analyzers/rsa.go   2021-09-20 23:52:51.000000000 +0200
@@ -173,9 +173,9 @@
 
                                // Check if argument of vulnerable function has 
keylen that is less than RECOMMENDED_KEYLEN
                                if keylen_check(pass, 
vulnFunc.Instr.Call.Args[1], call_graph) {
-                                       message := fmt.Sprintf("Danger: key 
length is too short, recommend %d", RECOMMENDED_KEYLEN)
+                                       message := fmt.Sprintf("Danger: RSA key 
length is too short, recommend %d", RECOMMENDED_KEYLEN)
                                        targetFunc := 
util.GenerateTaintedCode(pass, vulnFunc.Fn, vulnFunc.Instr.Pos())
-                                       results = append(results, 
util.MakeFinding(message, targetFunc, nil, "RSA Key Length"))
+                                       results = append(results, 
util.MakeFinding(message, targetFunc, nil, "CWE-326: Inadequate Encryption 
Strength"))
                                }
                        }
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/rsa_test.go 
new/gokart-0.3.0/analyzers/rsa_test.go
--- old/gokart-0.2.0/analyzers/rsa_test.go      2021-08-27 20:22:38.000000000 
+0200
+++ new/gokart-0.3.0/analyzers/rsa_test.go      2021-09-20 23:52:51.000000000 
+0200
@@ -51,7 +51,7 @@
        }
        for i := 0; i < len(testFiles); i++ {
                t.Run(testFiles[i], func(t *testing.T) {
-                       testutil.RunTest(testFiles[i], testResults[i], "RSA Key 
Length", RsaKeylenAnalyzer, t)
+                       testutil.RunTest(testFiles[i], testResults[i], 
"CWE-326: Inadequate Encryption Strength", RsaKeylenAnalyzer, t)
                })
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/scan.go 
new/gokart-0.3.0/analyzers/scan.go
--- old/gokart-0.2.0/analyzers/scan.go  2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/analyzers/scan.go  2021-09-20 23:52:51.000000000 +0200
@@ -19,6 +19,8 @@
 package analyzers
 
 import (
+       "encoding/json"
+       "errors"
        "fmt"
        "log"
        "os"
@@ -59,6 +61,7 @@
 
 func OutputResults(results []util.Finding, success bool) error {
        var stdOutPipe, outputFile *os.File
+       var outputColor = true
 
        if util.Config.OutputPath != "" {
                stdOutPipe = os.Stdout // keep backup of the real stdout
@@ -68,10 +71,27 @@
                        return err
                }
                os.Stdout = outputFile
+               outputColor = false
+       }
+
+       if util.Config.OutputJSON && success {
+               res, err := json.Marshal(results)
+               if err != nil {
+                       return err
+               }
+               fmt.Println(string(res))
+       }
+
+       if util.Config.OutputJSON && success {
+               res, err := json.Marshal(results)
+               if err != nil {
+                       return err
+               }
+               fmt.Println(string(res))
        }
 
        for _, finding := range results {
-               util.OutputFinding(finding)
+               util.OutputFinding(finding, outputColor)
        }
 
        // if packages were able to be scanned, print the correct output message
@@ -82,6 +102,8 @@
 
        // if output was redirected for findings, change it back to the 
original stdout
        if util.Config.OutputPath != "" {
+               // also generate the count of findings identified to the output 
file
+               util.OutputFindingMetadata(results, outputColor)
                outputFile.Close()
                os.Stdout = stdOutPipe // restoring the real stdout
        }
@@ -89,7 +111,7 @@
        return nil
 }
 
-func Scan(args []string) {
+func Scan(args []string) ([]util.Finding, error) {
        //Get the current dir so we can reset it later.
        current_dir, err := os.Getwd()
        if err != nil {
@@ -98,6 +120,8 @@
 
        if util.Config.OutputSarif {
                util.InitSarifReporting()
+       } else if util.Config.OutputJSON {
+               // don't print out anything
        } else {
                fmt.Printf("\nRevving engines VRMMM VRMMM\n3...2...1...Go!\n")
        }
@@ -185,9 +209,18 @@
                log.Fatalf("Error opening output file: %v", err)
        }
 
-       if !util.Config.OutputSarif && success {
+       // Don't print out messages if JSON or SARIF output
+       if !(util.Config.OutputSarif || util.Config.OutputJSON) && success {
                fmt.Println("\nRace Complete! Analysis took", scan_time, "and", 
util.FilesFound, "Go files were scanned (including imported packages)")
                fmt.Printf("GoKart found %d potentially vulnerable 
functions\n", len(filteredResults))
+               // display information about all findings
+               util.OutputFindingMetadata(filteredResults, true)
        }
        os.Chdir(current_dir)
+
+       if !success {
+               return nil, errors.New("gokart could not find any packages to 
scan")
+       }
+
+       return filteredResults, nil
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/sqli.go 
new/gokart-0.3.0/analyzers/sqli.go
--- old/gokart-0.2.0/analyzers/sqli.go  2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/analyzers/sqli.go  2021-09-20 23:52:51.000000000 +0200
@@ -80,7 +80,7 @@
                                        message := "Danger: possible SQL 
injection detected"
                                        targetFunc := 
util.GenerateTaintedCode(pass, vulnFunc.Fn, vulnFunc.Instr.Pos())
                                        taintSource := 
taint_analyzer.TaintSource
-                                       results = append(results, 
util.MakeFinding(message, targetFunc, taintSource, "SQL Injection"))
+                                       results = append(results, 
util.MakeFinding(message, targetFunc, taintSource, "CWE-89: SQL Injection"))
                                }
                        }
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/sqli_test.go 
new/gokart-0.3.0/analyzers/sqli_test.go
--- old/gokart-0.2.0/analyzers/sqli_test.go     2021-08-27 20:22:38.000000000 
+0200
+++ new/gokart-0.3.0/analyzers/sqli_test.go     2021-09-20 23:52:51.000000000 
+0200
@@ -39,7 +39,7 @@
        }
        for i := 0; i < len(testFiles); i++ {
                t.Run(testFiles[i], func(t *testing.T) {
-                       testutil.RunTest(testFiles[i], testResults[i], "SQL 
Injection", SQLInjectionAnalyzer, t)
+                       testutil.RunTest(testFiles[i], testResults[i], "CWE-89: 
SQL Injection", SQLInjectionAnalyzer, t)
                })
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/ssrf.go 
new/gokart-0.3.0/analyzers/ssrf.go
--- old/gokart-0.2.0/analyzers/ssrf.go  2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/analyzers/ssrf.go  2021-09-20 23:52:51.000000000 +0200
@@ -158,7 +158,7 @@
                                                                message := 
"Danger: possible SSRF detected"
                                                                targetFunc := 
util.GenerateTaintedCode(pass, vulnFunc.Fn, vulnFunc.Instr.Pos())
                                                                taintSource := 
taintAnalyzer.TaintSource
-                                                               results = 
append(results, util.MakeFinding(message, targetFunc, taintSource, "SSRF"))
+                                                               results = 
append(results, util.MakeFinding(message, targetFunc, taintSource, "CWE-918: 
Server-Side Request Forgery"))
 
                                                        }
                                                }
@@ -169,7 +169,7 @@
                                                        message := "Danger: 
possible SSRF detected"
                                                        targetFunc := 
util.GenerateTaintedCode(pass, vulnFunc.Fn, vulnFunc.Instr.Pos())
                                                        taintSource := 
taintAnalyzer.TaintSource
-                                                       results = 
append(results, util.MakeFinding(message, targetFunc, taintSource, "SSRF"))
+                                                       results = 
append(results, util.MakeFinding(message, targetFunc, taintSource, "CWE-918: 
Server-Side Request Forgery"))
 
                                                }
                                        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/ssrf_test.go 
new/gokart-0.3.0/analyzers/ssrf_test.go
--- old/gokart-0.2.0/analyzers/ssrf_test.go     2021-08-27 20:22:38.000000000 
+0200
+++ new/gokart-0.3.0/analyzers/ssrf_test.go     2021-09-20 23:52:51.000000000 
+0200
@@ -47,7 +47,7 @@
        }
        for i := 0; i < len(testFiles); i++ {
                t.Run(testFiles[i], func(t *testing.T) {
-                       testutil.RunTest(testFiles[i], testResults[i], "SSRF", 
SSRFAnalyzer, t)
+                       testutil.RunTest(testFiles[i], testResults[i], 
"CWE-918: Server-Side Request Forgery", SSRFAnalyzer, t)
                })
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/traversal.go 
new/gokart-0.3.0/analyzers/traversal.go
--- old/gokart-0.2.0/analyzers/traversal.go     2021-08-27 20:22:38.000000000 
+0200
+++ new/gokart-0.3.0/analyzers/traversal.go     2021-09-20 23:52:51.000000000 
+0200
@@ -75,7 +75,7 @@
 
                                        targetFunc := 
util.GenerateTaintedCode(pass, vulnFunc.Fn, vulnFunc.Instr.Pos())
                                        taintSource := taintAnalyzer.TaintSource
-                                       results = append(results, 
util.MakeFinding(message, targetFunc, taintSource, "Path Traversal"))
+                                       results = append(results, 
util.MakeFinding(message, targetFunc, taintSource, "CWE-22: Path Traversal"))
 
                                }
                        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/analyzers/traversal_test.go 
new/gokart-0.3.0/analyzers/traversal_test.go
--- old/gokart-0.2.0/analyzers/traversal_test.go        2021-08-27 
20:22:38.000000000 +0200
+++ new/gokart-0.3.0/analyzers/traversal_test.go        2021-09-20 
23:52:51.000000000 +0200
@@ -51,7 +51,7 @@
        }
        for i := 0; i < len(testFiles); i++ {
                t.Run(testFiles[i], func(t *testing.T) {
-                       testutil.RunTest(testFiles[i], testResults[i], "Path 
Traversal", PathTraversalAnalyzer, t)
+                       testutil.RunTest(testFiles[i], testResults[i], "CWE-22: 
Path Traversal", PathTraversalAnalyzer, t)
                })
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/cmd/scan.go new/gokart-0.3.0/cmd/scan.go
--- old/gokart-0.2.0/cmd/scan.go        2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/cmd/scan.go        2021-09-20 23:52:51.000000000 +0200
@@ -18,26 +18,34 @@
 package cmd
 
 import (
+       "io/ioutil"
        "log"
+       "os"
 
        "github.com/praetorian-inc/gokart/analyzers"
        "github.com/praetorian-inc/gokart/util"
        "github.com/spf13/cobra"
-
 )
 
 var yml string
-var goModName string
+var exitCode bool
+var remoteModule string
 var outputPath string
+var remoteBranch string
+var keyFile string
 
 func init() {
        goKartCmd.AddCommand(scanCmd)
        scanCmd.Flags().BoolP("sarif", "s", false, "outputs findings in SARIF 
form")
+       scanCmd.Flags().BoolP("json", "j", false, "outputs findings in JSON")
        scanCmd.Flags().BoolP("globalsTainted", "g", false, "marks global 
variables as dangerous")
        scanCmd.Flags().BoolP("verbose", "v", false, "outputs full trace of 
taint analysis")
        scanCmd.Flags().BoolP("debug", "d", false, "outputs debug logs")
-       scanCmd.Flags().StringVarP(&goModName, "remoteModule", "r", "", "Remote 
gomodule to scan")
-  scanCmd.Flags().StringVarP(&yml, "input", "i", "", "input path to custom yml 
file")
+       scanCmd.Flags().BoolP("exitCode", "x", false, "return non-nil exit code 
on potential vulnerabilities or scanner failure")
+       scanCmd.Flags().StringVarP(&remoteModule, "remoteModule", "r", "", 
"Remote gomodule to scan")
+       scanCmd.Flags().StringVarP(&remoteBranch, "remoteBranch", "b", "", 
"Branch of remote module to scan")
+       scanCmd.Flags().StringVarP(&keyFile, "keyFile", "k", "", "SSH Keyfile 
to use for ssh authentication for remote git repository scanning")
+       scanCmd.Flags().StringVarP(&yml, "input", "i", "", "input path to 
custom yml file")
        scanCmd.Flags().StringVarP(&outputPath, "output", "o", "", "file path 
to write findings output instead of stdout")
        goKartCmd.MarkFlagRequired("scan")
 }
@@ -49,31 +57,41 @@
 Scans a Go module directory. To scan the current directory recursively, use 
gokart scan. To scan a specific directory, use gokart scan <directory>.`,
        Run: func(cmd *cobra.Command, args []string) {
                sarif, _ := cmd.Flags().GetBool("sarif")
+               json, _ := cmd.Flags().GetBool("json")
                globals, _ := cmd.Flags().GetBool("globalsTainted")
                verbose, _ := cmd.Flags().GetBool("verbose")
                debug, _ := cmd.Flags().GetBool("debug")
-               util.InitConfig(globals, sarif, verbose, debug, outputPath, yml)
-               
-               // If gomodname flag is set to a non-empty value then clone the 
repo and scan it
-               if len(goModName) != 0 {
-                       modDirName, err := util.ParseModuleName(goModName)
+               exitCode, _ := cmd.Flags().GetBool("exitCode")
+               util.InitConfig(globals, sarif, json, verbose, debug, 
outputPath, yml, exitCode)
+
+               // If remoteModule was set, clone the remote repository and 
scan it
+               if len(remoteModule) != 0 {
+                       moduleTempDir, err := ioutil.TempDir(".", "gokart")
                        if err != nil {
-                               log.Fatal(err)
+                               log.Fatal("Error creating temporary directory: 
", err.Error())
                        }
-                       err = util.CloneModule(modDirName, "https://"+goModName)
+                       defer util.CleanupModule(moduleTempDir)
+
+                       // Clone the module, if the output format is JSON or 
SARIF don't print any progress to stdout
+                       err = util.CloneModule(moduleTempDir, remoteModule, 
remoteBranch, keyFile, json || sarif)
+
                        if err != nil {
-                               log.Fatal("GoKart was unable to get the new 
racetrack. Ensure track repository is open to the public or that your access 
tokens are configured correctly for Private ones.")
+                               util.CleanupModule(moduleTempDir)
+                               log.Fatal("Error cloning remote repository: ", 
err.Error())
                        }
-                       defer util.CleanupModule(modDirName)
                        // If passing in a module - the other arguments are 
wiped out!
-                       args = append([]string{}, modDirName+"/...")
+                       args = append([]string{}, moduleTempDir+"/...")
                }
 
                // recursively scan the current directory if no arguments are 
passed in
                if len(args) == 0 {
                        args = append(args, "./...")
                }
-               
-               analyzers.Scan(args)
+
+               results, err := analyzers.Scan(args)
+               // If we have set the flag to return non-zero exit code for 
when results are found or the scanner fails, return 1
+               if exitCode && (err != nil || len(results) > 0) {
+                       os.Exit(1)
+               }
        },
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/cmd/scan_test.go 
new/gokart-0.3.0/cmd/scan_test.go
--- old/gokart-0.2.0/cmd/scan_test.go   2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/cmd/scan_test.go   2021-09-20 23:52:51.000000000 +0200
@@ -1,77 +1,76 @@
-package cmd
-
-import (
-       "testing"
-       "strings"
-       "fmt"
-       "os"
-       "io/ioutil"
-       
-       "github.com/praetorian-inc/gokart/util"
-       "github.com/spf13/cobra"
-)
-
-func TestScanCommand(t *testing.T) {
-       // Tests the Scan command.
-       cur_dir, err := os.Getwd()
-       if err != nil {
-               fmt.Println(err)
-               os.Exit(1)
-       }
-       fmt.Printf("Current dir is: %s", cur_dir)
-       var tests = []struct {
-               args []string
-               expected_lastline string
-               moduledir string
-       }{
-               {[]string{"scan"},"GoKart found 0 potentially vulnerable 
functions", ""},
-               {[]string{"scan","-r", 
"github.com/Contrast-Security-OSS/go-test-bench"}, "GoKart found 8 potentially 
vulnerable functions", cur_dir+"/go-test-bench"},
-               {[]string{"scan","-r", "github.com/praetorian-inc/gokart"}, 
"GoKart found 0 potentially vulnerable functions", cur_dir+"/gokart"},
-               {[]string{"scan", "--help"}, "  -v, --verbose               
outputs full trace of taint analysis", ""},
-       }
-       for _, tt := range tests {
-               t.Run(strings.Join(tt.args, " "), func(t *testing.T) {
-                       
-                       if err != nil {
-                               t.Fatalf("Failed! %s",err)
-                       }
-
-                       // fetch last line of output from scan command
-                       lastline := ExecuteCommand(goKartCmd, tt.args)
-                       //if we tested with a remote module clean it up.
-                       if len(tt.moduledir) != 0 {
-                               err := util.CleanupModule(tt.moduledir)
-                               if err != nil {
-                                       fmt.Print(err)
-                               }
-                       }
-                       if lastline != tt.expected_lastline {
-                               t.Fatalf("Failed! Expected: %s\nGot: 
%s\n",tt.expected_lastline,lastline,)
-                       } 
-               })
-       }
-}
-
-func ExecuteCommand(cmd *cobra.Command,args []string) (string) {
-
-       // change stdout to something we can read from to capture command out
-       // Not sure if this could potentially cause issues if buffer gets too 
full
-       old := os.Stdout
-       r, w, _ := os.Pipe()
-       os.Stdout = w
-       os.Stderr = w
-
-       cmd.SetArgs(args)
-       Execute()
-
-       // reset stdout to normal stdout and read output from cmd
-       w.Close()
-       stdoutres, _ := ioutil.ReadAll(r)
-       os.Stdout = old
-
-       //get the last line of output for comparison with our tests
-       stdoutresslice := strings.Split(strings.ReplaceAll(string(stdoutres), 
"\r\n", "\n"), "\n")
-       lastline := stdoutresslice[len(stdoutresslice)-2]
-       return lastline
-
-}
\ No newline at end of file
+package cmd
+
+import (
+       "fmt"
+       "io/ioutil"
+       "os"
+       "strings"
+       "testing"
+
+       "github.com/praetorian-inc/gokart/util"
+       "github.com/spf13/cobra"
+)
+
+func TestScanCommand(t *testing.T) {
+       // Tests the Scan command.
+       cur_dir, err := os.Getwd()
+       if err != nil {
+               fmt.Println(err)
+               os.Exit(1)
+       }
+       fmt.Printf("Current dir is: %s", cur_dir)
+       var tests = []struct {
+               args              []string
+               expected_lastline string
+               moduledir         string
+       }{
+               {[]string{"scan"}, "GoKart found 0 potentially vulnerable 
functions", ""},
+        {[]string{"scan", "-r", "https://github.com/praetorian-inc/gokart"}, 
"GoKart found 0 potentially vulnerable functions", cur_dir + "/gokart"},
+               {[]string{"scan", "--help"}, "  -v, --verbose               
outputs full trace of taint analysis", ""},
+       }
+       for _, tt := range tests {
+               t.Run(strings.Join(tt.args, " "), func(t *testing.T) {
+
+                       if err != nil {
+                               t.Fatalf("Failed! %s", err)
+                       }
+
+                       // fetch last line of output from scan command
+                       lastline := ExecuteCommand(goKartCmd, tt.args)
+                       //if we tested with a remote module clean it up.
+                       if len(tt.moduledir) != 0 {
+                               err := util.CleanupModule(tt.moduledir)
+                               if err != nil {
+                                       fmt.Print(err)
+                               }
+                       }
+                       if lastline != tt.expected_lastline {
+                               t.Fatalf("Failed! Expected: %s\nGot: %s\n", 
tt.expected_lastline, lastline)
+                       }
+               })
+       }
+}
+
+func ExecuteCommand(cmd *cobra.Command, args []string) string {
+
+       // change stdout to something we can read from to capture command out
+       // Not sure if this could potentially cause issues if buffer gets too 
full
+       old := os.Stdout
+       r, w, _ := os.Pipe()
+       os.Stdout = w
+       os.Stderr = w
+
+       cmd.SetArgs(args)
+       Execute()
+
+       // reset stdout to normal stdout and read output from cmd
+       w.Close()
+       stdoutres, _ := ioutil.ReadAll(r)
+       os.Stdout = old
+
+       //get the last line of output for comparison with our tests
+       stdoutresslice := strings.Split(strings.ReplaceAll(string(stdoutres), 
"\r\n", "\n"), "\n")
+       lastline := stdoutresslice[len(stdoutresslice)-2]
+       return lastline
+
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/util/config.go 
new/gokart-0.3.0/util/config.go
--- old/gokart-0.2.0/util/config.go     2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/util/config.go     2021-09-20 23:52:51.000000000 +0200
@@ -30,8 +30,10 @@
 type ConfigType struct {
        GlobalsSafe bool
        OutputSarif bool
+       OutputJSON  bool
        Debug       bool
        Verbose     bool
+       ExitCode    bool
        YMLPath     string
        OutputPath  string
 }
@@ -121,18 +123,22 @@
 }
 
 // InitConfig() parses the flags and sets the corresponding Config variables
-func InitConfig(globals bool, sarif bool, verbose bool, debug bool, 
output_path string, yml string) {
+func InitConfig(globals bool, sarif bool, json bool, verbose bool, debug bool, 
output_path string, yml string, exitCode bool) {
        if yml == "" {
                yml = getDefaultConfigPath()
        } else if _, err := os.Stat(yml); err != nil {
                log.Fatalf("failed to find the provided config file at %s: %v", 
yml, err)
        }
-       fmt.Printf("Using config found at %s\n", yml)
+       if !(json || sarif) {
+               fmt.Printf("Using config found at %s\n", yml)
+       }
 
        Config.GlobalsSafe = !globals
        Config.OutputSarif = sarif
+       Config.OutputJSON = json
        Config.Debug = debug
        Config.Verbose = verbose
+       Config.ExitCode = exitCode
        Config.OutputPath = ""
        // get the absolute path of the output file to avoid issues when 
changing working directory for loading packages
        if output_path != "" {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/util/finding.go 
new/gokart-0.3.0/util/finding.go
--- old/gokart-0.2.0/util/finding.go    2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/util/finding.go    2021-09-20 23:52:51.000000000 +0200
@@ -16,6 +16,7 @@
 
 import (
        "fmt"
+       "log"
        "strings"
 
        "github.com/fatih/color"
@@ -57,43 +58,93 @@
                // if the source and sink are the same, return false and do not 
print out the finding
                return false
        }
+       // add filtering for findings with chan sources
+       if strings.Contains(finding.Untrusted_Source[0].SourceCode, 
"make(chan") {
+               if Config.Debug {
+                       log.Printf("Filtering Finding for Source: %s\n", 
finding.Untrusted_Source[0].SourceCode)
+               }
+               return false
+       }
        return true
 }
 
+func OutputFindingMetadata(results []Finding, outputColor bool) {
+       var ok bool
+       findingCounts := make(map[string]int)
+
+       for _, finding := range results {
+               _, ok = findingCounts[finding.Type]
+               if ok {
+                       findingCounts[finding.Type] += 1
+               } else {
+                       findingCounts[finding.Type] = 1
+               }
+       }
+
+       for findingType, count := range findingCounts {
+               if outputColor {
+                       yellow := color.New(color.FgYellow).SprintFunc()
+                       cyan := color.New(color.FgCyan).SprintFunc()
+                       fmt.Printf("Identified %s potential %s\n", 
yellow(count), cyan(findingType))
+               } else {
+                       fmt.Printf("Identified %d potential %s\n", count, 
findingType)
+               }
+       }
+}
+
 // prints out a finding
-func OutputFinding(finding Finding) {
+func OutputFinding(finding Finding, outputColor bool) {
        if Config.OutputSarif {
                SarifRecordFinding(finding.Type, finding.message, 
finding.Vulnerable_Function.SourceFilename,
                        finding.Vulnerable_Function.SourceLineNum)
+       } else if Config.OutputJSON {
+               // the JSON output is printed in OutputResults in scan.go, so 
nothing to do for this finding
+               return
        } else {
                yellow := color.New(color.FgYellow).SprintFunc()
                cyan := color.New(color.FgCyan).SprintFunc()
                green := color.New(color.FgGreen).SprintFunc()
+               red := color.New(color.FgRed).SprintFunc()
 
-               parentFunctionArgs := finding.Vulnerable_Function.ParentFunction
-               parentFunctionNoArgs := 
StripArguments(finding.Vulnerable_Function.ParentFunction)
+               sinkParentNoArgs := 
StripArguments(finding.Vulnerable_Function.ParentFunction)
 
-               fmt.Printf("\n(%s) %s\n\n", cyan(finding.Type), 
yellow(finding.message))
-               fmt.Printf("%s:%d\nVulnerable Function: [ %s ]\n", 
finding.Vulnerable_Function.SourceFilename, 
finding.Vulnerable_Function.SourceLineNum, parentFunctionNoArgs)
+               if outputColor {
+                       fmt.Printf("\n(%s) %s\n\n", cyan(finding.Type), 
yellow(finding.message))
+               } else {
+                       fmt.Printf("\n(%s) %s\n\n", finding.Type, 
finding.message)
+               }
+               fmt.Printf("%s:%d\nVulnerable Function: [ %s ]\n", 
finding.Vulnerable_Function.SourceFilename, 
finding.Vulnerable_Function.SourceLineNum, sinkParentNoArgs)
                fmt.Printf("      %d:\t%s\n", 
finding.Vulnerable_Function.SourceLineNum-1, 
GrabSourceCode(finding.Vulnerable_Function.SourceFilename, 
finding.Vulnerable_Function.SourceLineNum-1))
-               fmt.Printf("    > %d:\t%s\n", 
finding.Vulnerable_Function.SourceLineNum, 
finding.Vulnerable_Function.SourceCode)
+               if outputColor {
+                       fmt.Printf("    > %d:\t%s\n", 
finding.Vulnerable_Function.SourceLineNum, 
red(finding.Vulnerable_Function.SourceCode))
+               } else {
+                       fmt.Printf("    > %d:\t%s\n", 
finding.Vulnerable_Function.SourceLineNum, 
finding.Vulnerable_Function.SourceCode)
+               }
                fmt.Printf("      %d:\t%s\n", 
finding.Vulnerable_Function.SourceLineNum+1, 
GrabSourceCode(finding.Vulnerable_Function.SourceFilename, 
finding.Vulnerable_Function.SourceLineNum+1))
 
                if finding.Untrusted_Source != nil {
 
                        source := finding.Untrusted_Source[0]
                        fmt.Printf("\n%s:%d\n", source.SourceFilename, 
source.SourceLineNum)
-                       fmt.Printf("Source of Untrusted Input: [ %s ]\n", 
parentFunctionNoArgs)
+                       fmt.Printf("Source of Untrusted Input: [ %s ]\n", 
StripArguments(source.ParentFunction))
                        fmt.Printf("      %d:\t%s\n", source.SourceLineNum-1, 
GrabSourceCode(source.SourceFilename, source.SourceLineNum-1))
-                       fmt.Printf("    > %d:\t%s\n", source.SourceLineNum, 
source.SourceCode)
+                       if outputColor {
+                               fmt.Printf("    > %d:\t%s\n", 
source.SourceLineNum, red(source.SourceCode))
+                       } else {
+                               fmt.Printf("    > %d:\t%s\n", 
source.SourceLineNum, source.SourceCode)
+                       }
                        fmt.Printf("      %d:\t%s\n", source.SourceLineNum+1, 
GrabSourceCode(source.SourceFilename, source.SourceLineNum+1))
 
                        if Config.Verbose {
-                               
fmt.Print(green("\n############################### FULL TRACE 
###############################\n"))
+                               if outputColor {
+                                       
fmt.Print(green("\n############################### FULL TRACE 
###############################\n"))
+                               } else {
+                                       
fmt.Print("\n############################### FULL TRACE 
###############################\n")
+                               }
                                fmt.Printf("\nUntrusted Input Source:")
                                for _, source := range finding.Untrusted_Source 
{
                                        fmt.Printf("%s:%d:\n[ %s ]\n>>>\t%s\n", 
source.SourceFilename,
-                                               source.SourceLineNum, 
parentFunctionArgs, strings.TrimLeft(source.SourceCode, " \t"))
+                                               source.SourceLineNum, 
StripArguments(source.ParentFunction), strings.TrimLeft(source.SourceCode, " 
\t"))
                                }
                        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gokart-0.2.0/util/module.go 
new/gokart-0.3.0/util/module.go
--- old/gokart-0.2.0/util/module.go     2021-08-27 20:22:38.000000000 +0200
+++ new/gokart-0.3.0/util/module.go     2021-09-20 23:52:51.000000000 +0200
@@ -1,72 +1,71 @@
-// Copyright 2021 Praetorian Security, Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package util
-
-import (
-       "github.com/go-git/go-git/v5"
-       "fmt"
-       "strings"
-       "os"
-       "errors"
-)
-
-// CloneModule clones a remote git repository over HTTP.
-func CloneModule(dir string, url string) error {
-       // fmt.Printf("git clone %s\n", url)
-       fmt.Printf("Loading new racetrack: %s\n",url)
-
-       _, err := git.PlainClone(dir, false, &git.CloneOptions{
-               URL: url,
-               Progress: os.Stdout,
-       })
-       if err != nil {
-               return err
-       }
-
-       return nil
-}
-
-//CleanupModule attempts to delete a directory.
-func CleanupModule(dir string) error {
-       
-       err := os.RemoveAll(dir)
-       if err != nil{
-               return err
-       }
-       return nil
-}
-
-// ParseModuleName returns a directory from a module path 
-func ParseModuleName(mn string) (string, error) {
-
-       cur_dir, err := os.Getwd()
-       if err != nil {
-               return "", err
-       }
-
-       if len(mn) == 0 {
-               return "", errors.New("No module name provided")
-       }
-
-       modSlice := strings.Split(mn, "/")
-       if len(modSlice) <= 1 {
-               return "", errors.New("Invalid remote module name!\nMust be in 
format of: github.com/praetorian/gokart")
-       }
-
-       dirName := cur_dir + "/" + modSlice[len(modSlice)-1:][0]
-       return dirName, nil
-
-
-}
\ No newline at end of file
+// Copyright 2021 Praetorian Security, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package util
+
+import (
+       "log"
+       "os"
+
+       "github.com/go-git/go-git/v5"
+       "github.com/go-git/go-git/v5/plumbing"
+       "github.com/go-git/go-git/v5/plumbing/transport/ssh"
+)
+
+// CloneModule clones a remote git repository
+// An optional keyfile may be specified for use in ssh authentication
+// If quiet is true, don't print clone progress to stdout
+func CloneModule(dir string, url string, branch string, keyFile string, quiet 
bool) error {
+       var cloneOptions git.CloneOptions
+
+       cloneOptions = git.CloneOptions{
+               URL: url,
+       }
+
+       if !quiet {
+               log.Printf("Cloning new remote module: %s\n", url)
+               cloneOptions.Progress = os.Stdout
+       }
+
+       if len(branch) != 0 {
+               log.Printf("Cloning with remote branch reference: %s\n", branch)
+               cloneOptions.ReferenceName = 
plumbing.NewBranchReferenceName(branch)
+       }
+
+       if len(keyFile) != 0 {
+               _, err := os.Stat(keyFile)
+               if err != nil {
+                       log.Printf("Read file %s failed %s\n", keyFile, 
err.Error())
+                       return err
+               }
+
+               // Clone the given repository to the given directory (password 
set to "")
+               publicKeys, err := ssh.NewPublicKeysFromFile("git", keyFile, "")
+               if err != nil {
+                       log.Printf("Generate publickeys from file %s failed: 
%s\n", keyFile, err.Error())
+                       return err
+               }
+               log.Printf("Authenticating with ssh keyfile: %s\n", keyFile)
+               cloneOptions.Auth = publicKeys
+       }
+
+       _, err := git.PlainClone(dir, false, &cloneOptions)
+       return err
+}
+
+//CleanupModule attempts to delete a directory.
+func CleanupModule(dir string) error {
+       err := os.RemoveAll(dir)
+       return err
+}

++++++ vendor.tar.gz ++++++

Reply via email to