From 039bedd3f5831f7589b41d7fcbb0023aff817dbf Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Mon, 25 Apr 2022 15:29:05 +0100 Subject: [PATCH 1/3] fix: Use correct absolute Windows paths --- go.mod | 2 +- go.sum | 14 +++++++ internal/app/tfsec/cmd/flags.go | 68 +++++++++++++++++-------------- internal/app/tfsec/cmd/output.go | 18 ++++---- internal/app/tfsec/cmd/root.go | 2 +- internal/pkg/formatter/default.go | 20 ++++++--- test/flags_test.go | 2 +- 7 files changed, 77 insertions(+), 49 deletions(-) diff --git a/go.mod b/go.mod index 8f798c40ef..3fdd283f3a 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( github.com/AlecAivazis/survey/v2 v2.3.4 github.com/Masterminds/semver v1.5.0 - github.com/aquasecurity/defsec v0.38.0 + github.com/aquasecurity/defsec v0.43.0 github.com/hashicorp/go-version v1.4.0 github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf github.com/liamg/clinch v1.5.6 diff --git a/go.sum b/go.sum index 0a755ff60b..89595d65a1 100644 --- a/go.sum +++ b/go.sum @@ -196,6 +196,20 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6 github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/aquasecurity/defsec v0.38.0 h1:jh9XCBIM7eIrYwdI4MpwcFBktB8ua+kc/s5IHCkBXEc= github.com/aquasecurity/defsec v0.38.0/go.mod h1:/LFRX/+LFRViQPId8Nesgl1oNM6Fo86NH/V9Mu4akDA= +github.com/aquasecurity/defsec v0.38.1-0.20220425105347-2d6144076c6e h1:3IVhGWAPMApugdEZdPAxZOiGSjFYBF1EmmHcWZS+Lm8= +github.com/aquasecurity/defsec v0.38.1-0.20220425105347-2d6144076c6e/go.mod h1:/LFRX/+LFRViQPId8Nesgl1oNM6Fo86NH/V9Mu4akDA= +github.com/aquasecurity/defsec v0.40.0 h1:txQ8M0RGnrvBoHhEDmV53TJq9v/DKYClCFBTsI++wn0= +github.com/aquasecurity/defsec v0.40.0/go.mod h1:/LFRX/+LFRViQPId8Nesgl1oNM6Fo86NH/V9Mu4akDA= +github.com/aquasecurity/defsec v0.41.0 h1:LK4hbuSA6YuOEwp3pi9U/XdfedctENJsolpmZ3m5MUo= +github.com/aquasecurity/defsec v0.41.0/go.mod h1:/LFRX/+LFRViQPId8Nesgl1oNM6Fo86NH/V9Mu4akDA= +github.com/aquasecurity/defsec v0.42.0 h1:dHKEVIXftgJvifr2yGjXDMLR+W4WLtbkJASlObbGS7g= +github.com/aquasecurity/defsec v0.42.0/go.mod h1:/LFRX/+LFRViQPId8Nesgl1oNM6Fo86NH/V9Mu4akDA= +github.com/aquasecurity/defsec v0.42.1 h1:hOmGXUpjjCsZhkNI8SvMnqMKQxU4yclk8rmaDusioqs= +github.com/aquasecurity/defsec v0.42.1/go.mod h1:/LFRX/+LFRViQPId8Nesgl1oNM6Fo86NH/V9Mu4akDA= +github.com/aquasecurity/defsec v0.42.2-0.20220425141632-404c68bfeda9 h1:KDCK+DJ2Ez50apAbMo5baU2nocLm5XZBdHnB1lrL2S8= +github.com/aquasecurity/defsec v0.42.2-0.20220425141632-404c68bfeda9/go.mod h1:/LFRX/+LFRViQPId8Nesgl1oNM6Fo86NH/V9Mu4akDA= +github.com/aquasecurity/defsec v0.43.0 h1:3rnumsRe4liFmfHk43Pr6HaM6fd5lDiXSDijQKNDUAU= +github.com/aquasecurity/defsec v0.43.0/go.mod h1:/LFRX/+LFRViQPId8Nesgl1oNM6Fo86NH/V9Mu4akDA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= diff --git a/internal/app/tfsec/cmd/flags.go b/internal/app/tfsec/cmd/flags.go index 587f182e52..348cda5998 100644 --- a/internal/app/tfsec/cmd/flags.go +++ b/internal/app/tfsec/cmd/flags.go @@ -7,6 +7,8 @@ import ( "path/filepath" "strings" + "github.com/aquasecurity/defsec/pkg/scanners/options" + "github.com/aquasecurity/tfsec/internal/pkg/custom" "github.com/aquasecurity/defsec/pkg/scan" @@ -142,25 +144,25 @@ func excludeFunc(excludePaths []string) func(results scan.Results) scan.Results } } -func configureOptions(cmd *cobra.Command, fsRoot, dir string) ([]scanner.Option, error) { - - var options []scanner.Option - options = append( - options, - scanner.OptionWithSingleThread(singleThreadedMode), - scanner.OptionStopOnHCLError(!ignoreHCLErrors), - scanner.OptionStopOnRuleErrors(stopOnCheckError), - scanner.OptionSkipDownloaded(excludeDownloaded), - scanner.OptionScanAllDirectories(allDirs), - scanner.OptionWithWorkspaceName(workspace), - scanner.OptionWithAlternativeIDProvider(legacy.FindIDs), - scanner.OptionWithPolicyNamespaces("custom"), - scanner.OptionWithDownloads(!noModuleDownloads), - scanner.OptionWithRegoOnly(regoOnly), +func configureOptions(cmd *cobra.Command, fsRoot, dir string) ([]options.ScannerOption, error) { + + var scannerOptions []options.ScannerOption + scannerOptions = append( + scannerOptions, + scanner.ScannerWithSingleThread(singleThreadedMode), + scanner.ScannerWithStopOnHCLError(!ignoreHCLErrors), + scanner.ScannerWithStopOnRuleErrors(stopOnCheckError), + scanner.ScannerWithSkipDownloaded(excludeDownloaded), + scanner.ScannerWithAllDirectories(allDirs), + scanner.ScannerWithWorkspaceName(workspace), + scanner.ScannerWithAlternativeIDProvider(legacy.FindIDs), + options.ScannerWithPolicyNamespaces("custom"), + scanner.ScannerWithDownloadsAllowed(!noModuleDownloads), + scanner.ScannerWithRegoOnly(regoOnly), ) if len(excludePaths) > 0 { - options = append(options, scanner.OptionWithResultsFilter(excludeFunc(excludePaths))) + scannerOptions = append(scannerOptions, scanner.ScannerWithResultsFilter(excludeFunc(excludePaths))) } if len(tfvarsPaths) > 0 { @@ -168,7 +170,7 @@ func configureOptions(cmd *cobra.Command, fsRoot, dir string) ([]scanner.Option, if err != nil { return nil, fmt.Errorf("tfvars problem: %w", err) } - options = append(options, scanner.OptionWithTFVarsPaths(fixedPaths)) + scannerOptions = append(scannerOptions, scanner.ScannerWithTFVarsPaths(fixedPaths...)) } if regoPolicyDir != "" { @@ -176,11 +178,11 @@ func configureOptions(cmd *cobra.Command, fsRoot, dir string) ([]scanner.Option, if err != nil { return nil, fmt.Errorf("rego policy dir problem: %w", err) } - options = append(options, scanner.OptionWithPolicyDirs(fixedPath)) + scannerOptions = append(scannerOptions, options.ScannerWithPolicyDirs(fixedPath)) } if disableIgnores { - options = append(options, scanner.OptionNoIgnores()) + scannerOptions = append(scannerOptions, scanner.ScannerWithNoIgnores()) } if minimumSeverity != "" { @@ -188,33 +190,33 @@ func configureOptions(cmd *cobra.Command, fsRoot, dir string) ([]scanner.Option, if sev == severity.None { return nil, fmt.Errorf("'%s' is not a valid severity - should be one of CRITICAL, HIGH, MEDIUM, LOW", minimumSeverity) } - options = append(options, scanner.OptionWithMinimumSeverity(sev)) + scannerOptions = append(scannerOptions, scanner.ScannerWithMinimumSeverity(sev)) } if filterResults != "" { longIDs := strings.Split(filterResults, ",") - options = append(options, scanner.OptionIncludeRules(longIDs)) + scannerOptions = append(scannerOptions, scanner.ScannerWithIncludedRules(longIDs)) } if excludedRuleIDs != "" { - options = append(options, scanner.OptionExcludeRules(strings.Split(excludedRuleIDs, ","))) + scannerOptions = append(scannerOptions, scanner.ScannerWithExcludedRules(strings.Split(excludedRuleIDs, ","))) } if debug { - options = append(options, scanner.OptionWithDebug(cmd.ErrOrStderr())) + scannerOptions = append(scannerOptions, options.ScannerWithDebug(cmd.ErrOrStderr())) } if printRegoInput { - options = append(options, scanner.OptionWithStateFunc(func(s *state.State) { + scannerOptions = append(scannerOptions, scanner.ScannerWithStateFunc(func(s *state.State) { data, _ := json.Marshal(s.ToRego()) _, _ = fmt.Fprintf(cmd.OutOrStdout(), "\n%s\n\n", string(data)) })) } - return applyConfigFiles(options, dir) + return applyConfigFiles(scannerOptions, dir) } -func applyConfigFiles(options []scanner.Option, dir string) ([]scanner.Option, error) { +func applyConfigFiles(options []options.ScannerOption, dir string) ([]options.ScannerOption, error) { if configFile == "" { configDir := filepath.Join(dir, ".tfsec") for _, filename := range []string{"config.json", "config.yml", "config.yaml"} { @@ -231,11 +233,17 @@ func applyConfigFiles(options []scanner.Option, dir string) ([]scanner.Option, e return nil, fmt.Errorf("minimum tfsec version requirement not satisfied") } if conf.MinimumSeverity != "" { - options = append(options, scanner.OptionWithMinimumSeverity(severity.StringToSeverity(conf.MinimumSeverity))) + options = append(options, scanner.ScannerWithMinimumSeverity(severity.StringToSeverity(conf.MinimumSeverity))) + } + if len(conf.SeverityOverrides) > 0 { + options = append(options, scanner.ScannerWithSeverityOverrides(conf.SeverityOverrides)) + } + if len(conf.IncludedChecks) > 0 { + options = append(options, scanner.ScannerWithIncludedRules(conf.IncludedChecks)) + } + if len(conf.ExcludedChecks) > 0 { + options = append(options, scanner.ScannerWithExcludedRules(append(conf.ExcludedChecks, excludedRuleIDs))) } - options = append(options, scanner.OptionWithSeverityOverrides(conf.SeverityOverrides)) - options = append(options, scanner.OptionIncludeRules(conf.IncludedChecks)) - options = append(options, scanner.OptionExcludeRules(append(conf.ExcludedChecks, excludedRuleIDs))) } } if customCheckDir == "" { diff --git a/internal/app/tfsec/cmd/output.go b/internal/app/tfsec/cmd/output.go index 889a274fe8..135129a2e5 100644 --- a/internal/app/tfsec/cmd/output.go +++ b/internal/app/tfsec/cmd/output.go @@ -17,14 +17,14 @@ import ( "github.com/liamg/tml" ) -func output(cmd *cobra.Command, baseFilename string, formats []string, dir string, results []scan.Result, metrics scanner.Metrics) error { +func output(cmd *cobra.Command, baseFilename string, formats []string, fsRoot, dir string, results []scan.Result, metrics scanner.Metrics) error { if baseFilename == "" && len(formats) > 1 { return fmt.Errorf("you must specify a base output filename with --out if you want to use multiple formats") } var files []string for _, format := range formats { - if filename, err := outputFormat(cmd.OutOrStdout(), len(formats) > 1, baseFilename, format, dir, results, metrics); err != nil { + if filename, err := outputFormat(cmd.OutOrStdout(), len(formats) > 1, baseFilename, format, fsRoot, dir, results, metrics); err != nil { return err } else if filename != "" { files = append(files, filename) @@ -66,7 +66,7 @@ func gatherLinks(result scan.Result) []string { return append(docsLink, links...) } -func outputFormat(w io.Writer, addExtension bool, baseFilename string, format string, dir string, results scan.Results, metrics scanner.Metrics) (string, error) { +func outputFormat(w io.Writer, addExtension bool, baseFilename, format, fsRoot, dir string, results scan.Results, metrics scanner.Metrics) (string, error) { factory := formatters.New(). WithDebugEnabled(debug). @@ -79,28 +79,24 @@ func outputFormat(w io.Writer, addExtension bool, baseFilename string, format st WithIncludePassed(includePassed) var alsoStdout bool - var makeRelative bool + makeRelative := true switch strings.ToLower(format) { case "lovely", "default": alsoStdout = true factory.WithCustomFormatterFunc(formatter.DefaultWithMetrics(metrics, conciseOutput)) case "json": - makeRelative = true factory.AsJSON() + makeRelative = false case "csv": - makeRelative = true factory.AsCSV() case "checkstyle": - makeRelative = true factory.AsCheckStyle() case "junit": - makeRelative = true factory.AsJUnit() case "text": factory.WithCustomFormatterFunc(formatter.DefaultWithMetrics(metrics, conciseOutput)).WithColoursEnabled(false) case "sarif": - makeRelative = true factory.AsSARIF() case "gif": factory.WithCustomFormatterFunc(formatter.GifWithMetrics(metrics)) @@ -109,7 +105,9 @@ func outputFormat(w io.Writer, addExtension bool, baseFilename string, format st } if makeRelative { - results.SetRelativeTo(dir) + results = results.RelativeTo(fsRoot, dir) + } else { + results = results.Absolute(fsRoot) } var outputPath string diff --git a/internal/app/tfsec/cmd/root.go b/internal/app/tfsec/cmd/root.go index 26afde8f5b..11f6097efa 100644 --- a/internal/app/tfsec/cmd/root.go +++ b/internal/app/tfsec/cmd/root.go @@ -88,7 +88,7 @@ func Root() *cobra.Command { } formats := strings.Split(format, ",") - if err := output(cmd, outputFlag, formats, rel, results, metrics); err != nil { + if err := output(cmd, outputFlag, formats, root, dir, results, metrics); err != nil { return fmt.Errorf("failed to write output: %w", err) } diff --git a/internal/pkg/formatter/default.go b/internal/pkg/formatter/default.go index 5ea43ea6cf..73ea33104b 100644 --- a/internal/pkg/formatter/default.go +++ b/internal/pkg/formatter/default.go @@ -100,11 +100,7 @@ func makeFilenameNice(first scan.Result, baseDir string) (string, string, []simp filename := innerRange.GetFilename() topFilename := filename var via []simpleLocation - if innerRange.GetSourcePrefix() == "" || strings.HasPrefix(innerRange.GetSourcePrefix(), ".") { - if relative, err := filepath.Rel(baseDir, filename); err == nil && !strings.Contains(relative, "..") { - filename = relative - } - } else { + if strings.HasPrefix(innerRange.GetSourcePrefix(), ".") { m := first.Metadata() mod := &m lastFilename := m.Range().GetFilename() @@ -314,7 +310,19 @@ func highlightCode(b formatters.ConfigurableFormatter, result scan.Result) error } } - content, err := fs.ReadFile(srcFS, filepath.ToSlash(innerRange.GetLocalFilename())) + base := b.BaseDir() + if len(base) >= 2 && base[0] != '/' && base[1] == ':' { + base += "/" + } + + fullPath := filepath.ToSlash(filepath.Join(filepath.ToSlash(base), filepath.ToSlash(innerRange.GetLocalFilename()))) + if strings.HasPrefix(fullPath, "/") { + fullPath = fullPath[1:] + } else if len(fullPath) > 2 && fullPath[1] == ':' { + fullPath = fullPath[3:] + } + + content, err := fs.ReadFile(srcFS, fullPath) if err != nil { return err } diff --git a/test/flags_test.go b/test/flags_test.go index 5e064ff898..62d271ba90 100644 --- a/test/flags_test.go +++ b/test/flags_test.go @@ -336,7 +336,7 @@ func Test_Flag_Debug(t *testing.T) { t.Run(flag, func(t *testing.T) { out, err, exit := runWithArgs("./testdata/pass", "-f", "json", flag) _ = parseJSON(t, out) - assert.Contains(t, err, "\n[debug:") + assert.Contains(t, err, "\n[scan:") assert.Equal(t, 0, exit) }) } From 0745ad414785959686755a72c639fb2ae82c2a1e Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Mon, 25 Apr 2022 15:46:55 +0100 Subject: [PATCH 2/3] Fix code highlighting for modules --- internal/pkg/formatter/default.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/internal/pkg/formatter/default.go b/internal/pkg/formatter/default.go index 73ea33104b..3f3cc68b91 100644 --- a/internal/pkg/formatter/default.go +++ b/internal/pkg/formatter/default.go @@ -315,11 +315,14 @@ func highlightCode(b formatters.ConfigurableFormatter, result scan.Result) error base += "/" } - fullPath := filepath.ToSlash(filepath.Join(filepath.ToSlash(base), filepath.ToSlash(innerRange.GetLocalFilename()))) - if strings.HasPrefix(fullPath, "/") { - fullPath = fullPath[1:] - } else if len(fullPath) > 2 && fullPath[1] == ':' { - fullPath = fullPath[3:] + fullPath := innerRange.GetLocalFilename() + if innerRange.GetSourcePrefix() == "" || strings.HasPrefix(innerRange.GetSourcePrefix(), ".") { + fullPath = filepath.ToSlash(filepath.Join(filepath.ToSlash(base), filepath.ToSlash(innerRange.GetLocalFilename()))) + if strings.HasPrefix(fullPath, "/") { + fullPath = fullPath[1:] + } else if len(fullPath) > 2 && fullPath[1] == ':' { + fullPath = fullPath[3:] + } } content, err := fs.ReadFile(srcFS, fullPath) From b56430e19a164cb5ccbf39ecc1ec8b7d20900dde Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Mon, 25 Apr 2022 15:49:14 +0100 Subject: [PATCH 3/3] Fix code highlighting for modules --- internal/pkg/formatter/default.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/pkg/formatter/default.go b/internal/pkg/formatter/default.go index 3f3cc68b91..3712d63bd1 100644 --- a/internal/pkg/formatter/default.go +++ b/internal/pkg/formatter/default.go @@ -294,6 +294,7 @@ func printCodeLine(w io.Writer, i int, code string) { ) } +// nolint func highlightCode(b formatters.ConfigurableFormatter, result scan.Result) error { srcFS := result.Metadata().Range().GetFS()