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-09-14 21:14:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gokart (Old) and /work/SRC/openSUSE:Factory/.gokart.new.1899 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gokart" Tue Sep 14 21:14:19 2021 rev:2 rq:918787 version:0.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/gokart/gokart.changes 2021-08-20 16:58:14.150840554 +0200 +++ /work/SRC/openSUSE:Factory/.gokart.new.1899/gokart.changes 2021-09-14 21:14:25.780407387 +0200 @@ -1,0 +2,14 @@ +Thu Sep 02 14:03:52 UTC 2021 - alexandre.vice...@suse.com + +- Update to version 0.2.0: + * 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 + +------------------------------------------------------------------- Old: ---- gokart-0.1.0.tar.gz New: ---- gokart-0.2.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gokart.spec ++++++ --- /var/tmp/diff_new_pack.ysxNu4/_old 2021-09-14 21:14:26.576408169 +0200 +++ /var/tmp/diff_new_pack.ysxNu4/_new 2021-09-14 21:14:26.576408169 +0200 @@ -17,7 +17,7 @@ Name: gokart -Version: 0.1.0 +Version: 0.2.0 Release: 0 Summary: Static analysis tool for securing Go code License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.ysxNu4/_old 2021-09-14 21:14:26.604408196 +0200 +++ /var/tmp/diff_new_pack.ysxNu4/_new 2021-09-14 21:14:26.604408196 +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.1.0</param> + <param name="revision">v0.2.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.ysxNu4/_old 2021-09-14 21:14:26.620408211 +0200 +++ /var/tmp/diff_new_pack.ysxNu4/_new 2021-09-14 21:14:26.620408211 +0200 @@ -1,4 +1,4 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/praetorian-inc/gokart.git</param> - <param name="changesrevision">ab619765ff5e3963f1b504516490b3a4f328f08f</param></service></servicedata> \ No newline at end of file + <param name="changesrevision">fecb3b0f40927e14053bbb6dfbce3160e8b388bb</param></service></servicedata> \ No newline at end of file ++++++ gokart-0.1.0.tar.gz -> gokart-0.2.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/README.md new/gokart-0.2.0/README.md --- old/gokart-0.1.0/README.md 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/README.md 2021-08-27 20:22:38.000000000 +0200 @@ -28,7 +28,9 @@ the answer is yes. By leveraging source-to-sink tracing and SSA, GoKart is capable of tracking variable taint between variable assignments, significantly improving the accuracy of findings. Our focus is on usability: pragmatically, that means we -have optimized our approaches to reduce false alarms. +have optimized our approaches to reduce false alarms. + +For more information, please read [our blog post](https://www.praetorian.com/blog/introducing-gokart/). ## Install @@ -132,6 +134,22 @@ # Output results in sarif format gokart scan go-test-bench/ -s + +# Output results to file +gokart scan go-test-bench/ -o gokart-go-test-bench.txt + +# 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) +# Repository will be cloned locally, scanned and deleted afterwards +gokart scan -r github.com/ShiftLeftSecurity/shiftleft-go-demo -v + +# 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 + +# 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 ``` 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.1.0/analyzers/cmdi.go new/gokart-0.2.0/analyzers/cmdi.go --- old/gokart-0.1.0/analyzers/cmdi.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/analyzers/cmdi.go 2021-08-27 20:22:38.000000000 +0200 @@ -65,7 +65,7 @@ // Construct full name of function current_function := pkg + "." + fn - // Iterate over occurences of vulnerable function in call graph + // Iterate over occurrences of vulnerable function in call graph for _, vulnFunc := range call_graph[current_function] { // Check if argument of vulnerable function is tainted by possibly user-controlled input diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/analyzers/generic.go new/gokart-0.2.0/analyzers/generic.go --- old/gokart-0.1.0/analyzers/generic.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/analyzers/generic.go 2021-08-27 20:22:38.000000000 +0200 @@ -15,13 +15,9 @@ package analyzers import ( - "io/ioutil" - "log" - "github.com/praetorian-inc/gokart/util" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/buildssa" - "gopkg.in/yaml.v3" ) // Creates generic taint analyzer based on Sources and Sinks defined in analyzers.yaml file @@ -46,7 +42,7 @@ for _, fn := range funcs { // Construct full name of function currentFunc := pkg + "." + fn - // Iterate over occurences of vulnerable function in call graph + // Iterate over occurrences of vulnerable function in call graph for _, vulnFunc := range cg[currentFunc] { // Check if argument of vulnerable function is tainted by possibly user-controlled input taintAnalyzer := util.CreateTaintAnalyzer(pass, vulnFunc.Fn.Pos()) @@ -63,56 +59,23 @@ return results, nil } -// LoadGenericAnalyzers creates generic taint anlalyzers from custom Sources and Sinks defined in analyzers.yaml +// LoadGenericAnalyzers creates generic taint analyzers from custom Sources and Sinks defined in analyzers.yaml // converts all variables to SSA form to construct a call graph and performs // recursive taint analysis to search for input sources of user-controllable data +func LoadGenericAnalyzers() []*analysis.Analyzer { + var analyzers []*analysis.Analyzer -func LoadGenericAnalyzers(yaml_path string) []*analysis.Analyzer { - yfile, err := ioutil.ReadFile(yaml_path) - if err != nil { - log.Fatal(err) - } - - data := make(map[interface{}]map[interface{}]map[interface{}]interface{}) - err = yaml.Unmarshal(yfile, &data) - if err != nil { - log.Fatal(err) - } - - // Load analyzers from the interface - analyzers := []*analysis.Analyzer{} - m := data["analyzers"] - for analyzerName, analyzerDict := range m { - // Get the vulnerability message - message := "" - if analyzerDict["message"] != nil { - message = analyzerDict["message"].(string) - } - - // Load the map of vulnerable functions - vulnCalls := make(map[string][]string) - yamlCallsMap := analyzerDict["vuln_calls"].(map[string]interface{}) - for pkgName, packageVulnFuncs := range yamlCallsMap { - var newList []string - vulnCalls[pkgName] = newList - packageVulnFuncsList := packageVulnFuncs.([]interface{}) - for _, val := range packageVulnFuncsList { - vulnCalls[pkgName] = append(vulnCalls[pkgName], val.(string)) - } - } - - // Wrap generic_function_run with a function that the analyze package can use + for analyzerName, analyzerDict := range util.ScanConfig.Analyzers { analyzerFunc := func(pass *analysis.Pass) (interface{}, error) { - return genericFunctionRun(pass, vulnCalls, analyzerName.(string), message) + return genericFunctionRun(pass, analyzerDict.VulnCalls, analyzerName, analyzerDict.Message) } - - // Form the analyzer object and append to the analyzer list - analysisRun := new(analysis.Analyzer) - analysisRun.Name = "path_traversal" - analysisRun.Doc = analyzerDict["doc"].(string) - analysisRun.Run = analyzerFunc - analysisRun.Requires = []*analysis.Analyzer{buildssa.Analyzer} - analyzers = append(analyzers, analysisRun) + analysisRun := analysis.Analyzer{ + Name: analyzerName, + Doc: analyzerDict.Doc, + Run: analyzerFunc, + Requires: []*analysis.Analyzer{buildssa.Analyzer}, + } + analyzers = append(analyzers, &analysisRun) } return analyzers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/analyzers/rsa.go new/gokart-0.2.0/analyzers/rsa.go --- old/gokart-0.1.0/analyzers/rsa.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/analyzers/rsa.go 2021-08-27 20:22:38.000000000 +0200 @@ -28,7 +28,7 @@ // RSAKeyLenAnalyzer is used to resolve constant values used for RSA key generation in order to more accurately // detect use of an insecure RSA key length constructed -// all variables are converted to SSA form and a call graph is contructed +// all variables are converted to SSA form and a call graph is constructed // recursive analysis is then used to resolve variables used as a key length to a final constant value at the callsite var RsaKeylenAnalyzer = &analysis.Analyzer{ Name: "rsa_keylen", @@ -168,7 +168,7 @@ // Construct full name of function current_function := pkg + "." + fn - // Iterate over occurences of vulnerable function in call graph + // Iterate over occurrences of vulnerable function in call graph for _, vulnFunc := range call_graph[current_function] { // Check if argument of vulnerable function has keylen that is less than RECOMMENDED_KEYLEN diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/analyzers/scan.go new/gokart-0.2.0/analyzers/scan.go --- old/gokart-0.1.0/analyzers/scan.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/analyzers/scan.go 2021-08-27 20:22:38.000000000 +0200 @@ -39,17 +39,73 @@ SSRFAnalyzer, } +func FilterResults(unfilteredResults []util.Finding, parent_dir string) ([]util.Finding, error) { + filteredResults := []util.Finding{} + + for _, finding := range unfilteredResults { + finding.Vulnerable_Function.SourceFilename = strings.TrimPrefix(finding.Vulnerable_Function.SourceFilename, parent_dir) + if finding.Untrusted_Source != nil { + for i, source := range finding.Untrusted_Source { + finding.Untrusted_Source[i].SourceFilename = strings.TrimPrefix(source.SourceFilename, parent_dir) + } + } + if util.IsValidFinding(finding) { + filteredResults = append(filteredResults, finding) + } + } + + return filteredResults, nil +} + +func OutputResults(results []util.Finding, success bool) error { + var stdOutPipe, outputFile *os.File + + if util.Config.OutputPath != "" { + stdOutPipe = os.Stdout // keep backup of the real stdout + // open file read/write | create if not exist | clear file at open if exists + outputFile, err := os.OpenFile(util.Config.OutputPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + return err + } + os.Stdout = outputFile + } + + for _, finding := range results { + util.OutputFinding(finding) + } + + // if packages were able to be scanned, print the correct output message + if util.Config.OutputSarif && success { + util.SarifPrintReport() + fmt.Println() + } + + // if output was redirected for findings, change it back to the original stdout + if util.Config.OutputPath != "" { + outputFile.Close() + os.Stdout = stdOutPipe // restoring the real stdout + } + + return nil +} + func Scan(args []string) { + //Get the current dir so we can reset it later. + current_dir, err := os.Getwd() + if err != nil { + fmt.Printf("Unable to get current dir.\n") + } + if util.Config.OutputSarif { util.InitSarifReporting() } else { fmt.Printf("\nRevving engines VRMMM VRMMM\n3...2...1...Go!\n") } - // If we're given a target path, we do some slight changes to make sure that // gokart will behave as expected. Specifically we turn the path into an absolute // path, and then we append /... to the end to make sure the package loading is recursive. // Finally we update the current working directory to the target + // In order to not cause issues we set the working directory back after we are done scanning. if len(args) > 0 { target_path := args[0] if !filepath.IsAbs(target_path) { @@ -58,7 +114,7 @@ } // Fix up the path to make sure it is pointed at a directory (even if given a file) - fileInfo, err := os.Stat(strings.TrimRight(target_path, "...")) + fileInfo, err := os.Stat(strings.TrimRight(target_path, ".")) if err != nil { log.Fatal(err) } @@ -76,7 +132,7 @@ } } - err = os.Chdir(strings.TrimRight(target_path, "...")) + err = os.Chdir(strings.TrimRight(target_path, ".")) if err != nil { log.Fatal(err) } @@ -86,7 +142,7 @@ } } - generic_analyzers := LoadGenericAnalyzers(util.Config.YMLPath) + generic_analyzers := LoadGenericAnalyzers() Analyzers = append(Analyzers, generic_analyzers[:]...) // Begin timer @@ -94,7 +150,7 @@ // Run analyzers results, success, err := run.Run(Analyzers, args...) if err != nil { - panic(err) + log.Fatal(err) } // Calculate time taken scan_time := time.Since(run_begin_time) @@ -117,24 +173,21 @@ parent_dir += "/" } - count := 0 - for _, finding := range results { - finding.Vulnerable_Function.SourceFilename = strings.TrimPrefix(finding.Vulnerable_Function.SourceFilename, parent_dir) - if finding.Untrusted_Source != nil { - for i, source := range finding.Untrusted_Source { - finding.Untrusted_Source[i].SourceFilename = strings.TrimPrefix(source.SourceFilename, parent_dir) - } - } - if util.OutputFinding(finding) { - count++ - } + // fix-up our results to exclude invalid results + shorten long directory names + filteredResults, err := FilterResults(results, parent_dir) + if err != nil { + log.Fatal(err) } - // if packages were able to be scanned, print the correct output message - if util.Config.OutputSarif && success { - util.SarifPrintReport() - fmt.Println() - } else if success { + + // output findings to stdout or specified output file + err = OutputResults(filteredResults, success) + if err != nil { + log.Fatalf("Error opening output file: %v", err) + } + + if !util.Config.OutputSarif && 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", count) + fmt.Printf("GoKart found %d potentially vulnerable functions\n", len(filteredResults)) } + os.Chdir(current_dir) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/analyzers/sqli.go new/gokart-0.2.0/analyzers/sqli.go --- old/gokart-0.1.0/analyzers/sqli.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/analyzers/sqli.go 2021-08-27 20:22:38.000000000 +0200 @@ -23,7 +23,7 @@ ) // SQLInjectionAnalyzer constructs Sinks from a set of functions known to be vulnerable to SQL injection -// all variables are converted to SSA form and a call graph is contructed +// all variables are converted to SSA form and a call graph is constructed // recursive taint analysis is then used to search from a given Sink up the callgraph for Sources of user-controllable data var SQLInjectionAnalyzer = &analysis.Analyzer{ Name: "sql_injection", @@ -71,7 +71,7 @@ argIndex = 2 } - // Iterate over occurences of vulnerable function in call graph + // Iterate over occurrences of vulnerable function in call graph for _, vulnFunc := range cg[current_function] { // Check if argument of vulnerable function is tainted by possibly user-controlled input diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/analyzers/ssrf.go new/gokart-0.2.0/analyzers/ssrf.go --- old/gokart-0.1.0/analyzers/ssrf.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/analyzers/ssrf.go 2021-08-27 20:22:38.000000000 +0200 @@ -143,7 +143,7 @@ // Construct full name of function curFunc := pkg + "." + fn - // Iterate over occurences of vulnerable function in call graph + // Iterate over occurrences of vulnerable function in call graph for _, vulnFunc := range cg[curFunc] { // Check if argument of vulnerable function is tainted by possibly user-controlled input taintAnalyzer := util.CreateTaintAnalyzer(pass, vulnFunc.Fn.Pos()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/analyzers/traversal.go new/gokart-0.2.0/analyzers/traversal.go --- old/gokart-0.1.0/analyzers/traversal.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/analyzers/traversal.go 2021-08-27 20:22:38.000000000 +0200 @@ -21,12 +21,12 @@ ) // PathTraversalAnalyzer constructs Sinks from a set of functions known to be vulnerable to path injection -// all variables are converted to SSA form and a call graph is contructed +// all variables are converted to SSA form and a call graph is constructed // recursive taint analysis is then used to search from a given Sink up the callgraph for Sources of user-controllable data var PathTraversalAnalyzer = &analysis.Analyzer{ Name: "path_traversal", Doc: "reports when path traversal can occur", - Run: traveralRun, + Run: traversalRun, Requires: []*analysis.Analyzer{buildssa.Analyzer}, } @@ -38,8 +38,8 @@ } } -// traveralRun runs the path traversal analyzer -func traveralRun(pass *analysis.Pass) (interface{}, error) { +// traversalRun runs the path traversal analyzer +func traversalRun(pass *analysis.Pass) (interface{}, error) { results := []util.Finding{} // Builds SSA model of Go code @@ -65,7 +65,7 @@ // Construct full name of function curFunc := pkg + "." + fn - // Iterate over occurences of vulnerable function in call graph + // Iterate over occurrences of vulnerable function in call graph for _, vulnFunc := range cg[curFunc] { // Check if argument of vulnerable function is tainted by possibly user-controlled input diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/cmd/scan.go new/gokart-0.2.0/cmd/scan.go --- old/gokart-0.1.0/cmd/scan.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/cmd/scan.go 2021-08-27 20:22:38.000000000 +0200 @@ -18,12 +18,17 @@ package cmd import ( + "log" + "github.com/praetorian-inc/gokart/analyzers" "github.com/praetorian-inc/gokart/util" "github.com/spf13/cobra" + ) var yml string +var goModName string +var outputPath string func init() { goKartCmd.AddCommand(scanCmd) @@ -31,7 +36,9 @@ 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(&yml, "input", "i", "", "input path to custom yml file") + scanCmd.Flags().StringVarP(&goModName, "remoteModule", "r", "", "Remote gomodule to scan") + 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") } @@ -41,15 +48,32 @@ Long: ` 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) { - if len(args) == 0 { - // recursively scan the current directory if no arguments are passed in - args = append(args, "./...") - } sarif, _ := cmd.Flags().GetBool("sarif") globals, _ := cmd.Flags().GetBool("globalsTainted") verbose, _ := cmd.Flags().GetBool("verbose") debug, _ := cmd.Flags().GetBool("debug") - util.InitConfig(globals, sarif, verbose, debug, yml) + 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) + if err != nil { + log.Fatal(err) + } + err = util.CloneModule(modDirName, "https://"+goModName) + 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.") + } + defer util.CleanupModule(modDirName) + // If passing in a module - the other arguments are wiped out! + args = append([]string{}, modDirName+"/...") + } + + // recursively scan the current directory if no arguments are passed in + if len(args) == 0 { + args = append(args, "./...") + } + analyzers.Scan(args) }, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/cmd/scan_test.go new/gokart-0.2.0/cmd/scan_test.go --- old/gokart-0.1.0/cmd/scan_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/gokart-0.2.0/cmd/scan_test.go 2021-08-27 20:22:38.000000000 +0200 @@ -0,0 +1,77 @@ +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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/go.mod new/gokart-0.2.0/go.mod --- old/gokart-0.1.0/go.mod 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/go.mod 2021-08-27 20:22:38.000000000 +0200 @@ -4,6 +4,7 @@ require ( github.com/fatih/color v1.12.0 + github.com/go-git/go-git/v5 v5.4.2 // indirect github.com/lithammer/dedent v1.1.0 github.com/owenrumney/go-sarif v1.0.11 github.com/segmentio/fasthash v1.0.3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/go.sum new/gokart-0.2.0/go.sum --- old/gokart-0.1.0/go.sum 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/go.sum 2021-08-27 20:22:38.000000000 +0200 @@ -39,11 +39,20 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= +github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -57,9 +66,12 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -70,8 +82,18 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= +github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= +github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= +github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= +github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -163,23 +185,34 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= +github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -189,6 +222,8 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= @@ -198,11 +233,13 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/owenrumney/go-sarif v1.0.11 h1:7k4TLSi6h3vAozSECjO0arcQoeUNDMgvA7LDac95sJo= github.com/owenrumney/go-sarif v1.0.11/go.mod h1:hTBFbxU7GuVRUvwMx+eStp9M/Oun4xHCS3vqpPvket8= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -215,7 +252,10 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= @@ -227,6 +267,7 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -237,6 +278,8 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= +github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -258,12 +301,16 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -335,6 +382,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -361,6 +410,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -370,6 +420,7 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -398,8 +449,10 @@ golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -577,11 +630,18 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/run/run.go new/gokart-0.2.0/run/run.go --- old/gokart-0.1.0/run/run.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/run/run.go 2021-08-27 20:22:38.000000000 +0200 @@ -88,7 +88,8 @@ } // Print error mssage if no scannable packages are found if len(pkgs) == 0 { - fmt.Printf("CRASH! GoKart didn't find any files to scan! Make sure the usage is correct to get GoKart back on track. \n") + fmt.Printf("CRASH! GoKart didn't find any files to scan! Make sure the usage is correct to get GoKart back on track. \n" + + "If the usage appears to be correct, try pointing gokart at the directory from where you would run 'go build'. \n") success = false } return pkgs, success, nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/util/analyzers.yml new/gokart-0.2.0/util/analyzers.yml --- old/gokart-0.1.0/util/analyzers.yml 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/util/analyzers.yml 2021-08-27 20:22:38.000000000 +0200 @@ -33,66 +33,61 @@ # - "Printf" + +# Each entry specifies a source that should be considered untrusted +# If the package already exists in the sources section, add the variable/function/type underneath +# Each package can contain multiple vulnerable sources. sources: - # Each entry specifies a source that should be considered untrusted - # If the package already exists in the sources section, add the variable/function/type underneath - # Each package can contain multiple vulnerable sources. - sources: - # Sources that are defined in Go documentation as a "variable" go here (note: these variables will have an SSA type of "Global"). - variables: - "os": - - "Args" - # Sources that are defined in Go documentation as a "function" go here. - functions: - "flag": - - "Arg" - - "Args" - "os": - - "Environ" - - "File" - - "FileInfo" - - "FileMode" - - "Readdir" - - "Readdirnames" - - "OpenFile" - "crypto/tls": - - "LoadX509KeyPair" - - "X509KeyPair" - "os/user": - - "Lookup" - - "LookupId" - - "Current" - "crypto/x509": - - "Subjects" - "io": - - "ReadAtLeast" - - "ReadFull" - "database/sql": - - "Query" - - "QueryRow" - "bytes": - - "String" - - "ReadBytes" - - "ReadByte" - "bufio": - - "Text" - - "Bytes" - - "ReadString" - - "ReadSlice" - - "ReadRune" - - "ReadLine" - - "ReadBytes" - - "ReadByte" - "archive/tar": - - "Next" - - "FileInfo" - - "Header" - "net/url": - - "ParseQuery" - - "ParseUriRequest" - - "Parse" - - "Query" - # Sources that are defined in Go documentation as a "type" go here (note: adding types will consider all functions that use that type to be tainted). - types: - "net/http": - - "Request" + # Sources that are defined in Go documentation as a "variable" go here (note: these variables will have an SSA type of "Global"). + variables: + "os": + - "Args" + # Sources that are defined in Go documentation as a "function" go here. + functions: + "flag": + - "Arg" + - "Args" + "os": + - "Environ" + - "File" + "crypto/tls": + - "LoadX509KeyPair" + - "X509KeyPair" + "os/user": + - "Lookup" + - "LookupId" + - "Current" + "crypto/x509": + - "Subjects" + "io": + - "ReadAtLeast" + - "ReadFull" + "database/sql": + - "Query" + - "QueryRow" + "bytes": + - "String" + - "ReadBytes" + - "ReadByte" + "bufio": + - "Text" + - "Bytes" + - "ReadString" + - "ReadSlice" + - "ReadRune" + - "ReadLine" + - "ReadBytes" + - "ReadByte" + "archive/tar": + - "Next" + - "FileInfo" + - "Header" + "net/url": + - "ParseQuery" + - "ParseUriRequest" + - "Parse" + - "Query" + # Sources that are defined in Go documentation as a "type" go here (note: adding types will consider all functions that use that type to be tainted). + types: + "net/http": + - "Request" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/util/config.go new/gokart-0.2.0/util/config.go --- old/gokart-0.1.0/util/config.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/util/config.go 2021-08-27 20:22:38.000000000 +0200 @@ -16,13 +16,12 @@ import ( _ "embed" - "flag" "fmt" "io/ioutil" "log" "os" - "path" "path/filepath" + "sync" "gopkg.in/yaml.v3" ) @@ -34,6 +33,29 @@ Debug bool Verbose bool YMLPath string + OutputPath string +} + +// ConfigFile stores the values parsed from the configuration file +type ConfigFile struct { + Analyzers map[string]Analyzer `yaml:"analyzers"` + Sources Sources `yaml:"sources"` +} + +// Analyzer stores an analyzer parsed from the configuration file +type Analyzer struct { + Doc string `yaml:"doc"` + Message string `yaml:"message"` + VulnCalls map[string][]string `yaml:"vuln_calls"` +} + +// Sources stores the untrusted sources parsed from the configuration file +type Sources struct { + Variables map[string][]string `yaml:"variables"` + Functions map[string][]string `yaml:"functions"` + Types map[string][]string `yaml:"types"` + // For compatibility with older analyzer.yml format + OldSrcs *Sources `yaml:"sources"` } var ( @@ -45,115 +67,113 @@ DefaultAnalyzersContent []byte ) -var Config ConfigType +var ( + configDir string + once sync.Once +) -func LoadVulnerableSources() { - // Load YAML - yamlPath := Config.YMLPath - // If not found in the working directory, use the one in the executable's directory - if _, err := os.Stat(yamlPath); os.IsNotExist(err) { - execPath, err := os.Executable() - if err != nil { - log.Fatal(err) - } - yamlPath = path.Join(path.Dir(execPath), yamlPath) - } - yfile, err := ioutil.ReadFile(yamlPath) +var ( + Config ConfigType + ScanConfig ConfigFile +) + +func LoadScanConfig() { + configBytes, err := ioutil.ReadFile(Config.YMLPath) if err != nil { log.Fatal(err) } - - data := make(map[interface{}]map[interface{}]map[interface{}]interface{}) - err = yaml.Unmarshal(yfile, &data) - if err != nil { + if err := yaml.Unmarshal(configBytes, &ScanConfig); err != nil { log.Fatal(err) } - skeys := data["sources"] - if Config.Debug { - log.Println("Beginning list of sources defined in yml:") + // If OldSrcs isn't nil, then the config file is in the old format and we unnest the values + if ScanConfig.Sources.OldSrcs != nil { + ScanConfig.Sources.Functions = ScanConfig.Sources.OldSrcs.Functions + ScanConfig.Sources.Variables = ScanConfig.Sources.OldSrcs.Variables + ScanConfig.Sources.Types = ScanConfig.Sources.OldSrcs.Types + // Set OldSrcs to nil to let the garbage collector clean it up + ScanConfig.Sources.OldSrcs = nil } - for _, sdict := range skeys { - for stype, sTypeDict := range sdict { - callsmap := sTypeDict.(map[string]interface{}) - vulnmap := make(map[string][]string) - - for package_name, package_vuln_funcs := range callsmap { - // Initialize an empty array if the map key does not exist - if _, ok := vulnmap[package_name]; !ok { - var empty_array []string - vulnmap[package_name] = empty_array - } - package_vuln_funcs_arr := package_vuln_funcs.([]interface{}) - for i, val := range package_vuln_funcs_arr { - if Config.Debug { - log.Println("Function", package_vuln_funcs_arr[i], "in package", package_name) - } - vulnmap[package_name] = append(vulnmap[package_name], val.(string)) - } - } - // Set the map of vulnerable sources of this type - if stype == "variables" { - VulnGlobalVars = vulnmap - } else if stype == "functions" { - VulnGlobalFuncs = vulnmap - } else if stype == "types" { - VulnTypes = vulnmap + if Config.Debug { + log.Println("Beginning list of default sources defined in yml:") + for pkg, fn := range ScanConfig.Sources.Functions { + log.Printf("Functions %s in package %s\n", fn, pkg) + } + if len(ScanConfig.Analyzers) > 0 { + log.Println("\nBeginning list of analyzers defined in yml:") + for name, values := range ScanConfig.Analyzers { + log.Printf("Name: %s\n", name) + log.Printf("Doc: %s\n", values.Doc) + log.Printf("Message: %s\n", values.Message) + log.Println("Vuln Calls:") + for pkg, fn := range values.VulnCalls { + log.Printf("Functions %s in package %s\n", fn, pkg) + } } } + log.Printf("\n\n") } - if Config.Debug { - log.Println("List of sources complete") - } + VulnGlobalVars = ScanConfig.Sources.Variables + VulnGlobalFuncs = ScanConfig.Sources.Functions + VulnTypes = ScanConfig.Sources.Types } // InitConfig() parses the flags and sets the corresponding Config variables -func InitConfig(globals bool, sarif bool, verbose bool, debug bool, yml string) { - - flag.Parse() - - // If the YAML path provided is a relative path, convert it to absolute - if yml != "" && !filepath.IsAbs(yml) { - yml, _ = filepath.Abs(yml) +func InitConfig(globals bool, sarif bool, verbose bool, debug bool, output_path string, yml string) { + 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 the YAML path provided is empty or doesn't exist, then load from the default of ~/.gokart/analyzers.yml - if _, err := os.Stat(yml); os.IsNotExist(err) { - if yml != "" { - fmt.Printf("Custom analyzers config file not found at %q. ", yml) + Config.GlobalsSafe = !globals + Config.OutputSarif = sarif + Config.Debug = debug + Config.Verbose = verbose + Config.OutputPath = "" + // get the absolute path of the output file to avoid issues when changing working directory for loading packages + if output_path != "" { + abs_output_path, err := filepath.Abs(output_path) + if err != nil { + log.Fatal(err) } - fmt.Println("Using default analyzers config found at \"~/.gokart/analyzers.yml\".") - - // Load YAML - config_path := os.ExpandEnv("$HOME/.gokart") - yaml_path := path.Join(config_path, "analyzers.yml") - yml = yaml_path + Config.OutputPath = abs_output_path + } + Config.YMLPath = yml + LoadScanConfig() +} - // Create our config directory if it doesn't already exist - if _, err := os.Stat(config_path); os.IsNotExist(err) { - err = os.Mkdir(config_path, 0744) - if err != nil { - log.Fatal(err) - } - } +// getDefaultConfigPath gets the path to the default configuration file and creates it if it doesn't yet exist. +func getDefaultConfigPath() string { + setConfigDir() + yamlPath := filepath.Join(configDir, "analyzers.yml") - // If not found in the working directory, use the one in the executable's directory - if _, err := os.Stat(yaml_path); os.IsNotExist(err) { - // default_analyzers_content is populated using the go:embed directive above - err := ioutil.WriteFile(yaml_path, DefaultAnalyzersContent, 0744) - if err != nil { - log.Fatal(err) - } - fmt.Println("No existing analyzers.yml file found - writing default to ~/.gokart/analyzers.yml") + // If ~/.gokart/analyzers.yml doesn't exist, create it with the default config + if _, err := os.Stat(yamlPath); os.IsNotExist(err) { + fmt.Printf("Initializing default config at %s\n", yamlPath) + if err := ioutil.WriteFile(yamlPath, DefaultAnalyzersContent, 0o744); err != nil { + log.Fatalf("failed to write default config to %s: %v", yamlPath, err) } + } else if err != nil { + // If the error returned by os.Stat is not ErrNotExist + log.Fatalf("failed to initialize default config: %v", err) } + return yamlPath +} - Config.GlobalsSafe = !globals - Config.OutputSarif = sarif - Config.Debug = debug - Config.Verbose = verbose - Config.YMLPath = yml - LoadVulnerableSources() +// setConfigDir initializes the configDir variable upon its first invocation, does nothing otherwise. +func setConfigDir() { + once.Do(func() { + userHomeDir, err := os.UserHomeDir() + if err != nil { + log.Fatalf("failed to get home directory: %v", err) + } + configDir = filepath.Join(userHomeDir, ".gokart") + if err = os.MkdirAll(configDir, 0o744); err != nil { + log.Fatalf("failed to create config directory %s: %v", configDir, err) + } + }) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/util/finding.go new/gokart-0.2.0/util/finding.go --- old/gokart-0.1.0/util/finding.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/util/finding.go 2021-08-27 20:22:38.000000000 +0200 @@ -48,12 +48,20 @@ return strings.TrimSpace(functionName) + "(...)" + functionReturn } -// prints out a finding; returns true if the finding was valid and false if the finding had the same source and sink -func OutputFinding(finding Finding) bool { - // if the source and sink are the same, return false and do not print out the finding +// returns true if the finding was valid and false if the finding had the same source and sink +func IsValidFinding(finding Finding) bool { + if len(finding.Untrusted_Source) == 0 { + return false + } if finding.Vulnerable_Function.SourceCode == finding.Untrusted_Source[0].SourceCode { + // if the source and sink are the same, return false and do not print out the finding return false } + return true +} + +// prints out a finding +func OutputFinding(finding Finding) { if Config.OutputSarif { SarifRecordFinding(finding.Type, finding.message, finding.Vulnerable_Function.SourceFilename, finding.Vulnerable_Function.SourceLineNum) @@ -92,5 +100,4 @@ } fmt.Printf("------------------------------------------------------------------------------\n") } - return true } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/util/module.go new/gokart-0.2.0/util/module.go --- old/gokart-0.1.0/util/module.go 1970-01-01 01:00:00.000000000 +0100 +++ new/gokart-0.2.0/util/module.go 2021-08-27 20:22:38.000000000 +0200 @@ -0,0 +1,72 @@ +// 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gokart-0.1.0/util/sarif.go new/gokart-0.2.0/util/sarif.go --- old/gokart-0.1.0/util/sarif.go 2021-08-18 15:59:31.000000000 +0200 +++ new/gokart-0.2.0/util/sarif.go 2021-08-27 20:22:38.000000000 +0200 @@ -15,6 +15,7 @@ package util import ( + "log" "os" "github.com/owenrumney/go-sarif/sarif" @@ -27,7 +28,7 @@ report, err := sarif.New(sarif.Version210) SarifReport = report if err != nil { - panic(err) + log.Fatal(err) } SarifRun = sarif.NewRun("GoKart", "https://github.com/praetorian-inc/gokart") } ++++++ vendor.tar.gz ++++++ ++++ 111814 lines of diff (skipped)