diff --git a/cmd/osv-scanner/main.go b/cmd/osv-scanner/main.go index 7d80646fe0..c0c0df10f1 100644 --- a/cmd/osv-scanner/main.go +++ b/cmd/osv-scanner/main.go @@ -6,8 +6,8 @@ import ( "io" "os" - "github.com/google/osv-scanner/internal/output" "github.com/google/osv-scanner/pkg/osvscanner" + "github.com/google/osv-scanner/pkg/reporter" "github.com/urfave/cli/v2" ) @@ -20,10 +20,10 @@ var ( ) func run(args []string, stdout, stderr io.Writer) int { - var r *output.Reporter + var r *reporter.Reporter cli.VersionPrinter = func(ctx *cli.Context) { - r = output.NewReporter(ctx.App.Writer, ctx.App.ErrWriter, "") + r = reporter.NewReporter(ctx.App.Writer, ctx.App.ErrWriter, "") r.PrintText(fmt.Sprintf("osv-scanner version: %s\ncommit: %s\nbuilt at: %s\n", ctx.App.Version, commit, date)) } @@ -109,7 +109,7 @@ func run(args []string, stdout, stderr io.Writer) int { format = "json" } - r = output.NewReporter(stdout, stderr, format) + r = reporter.NewReporter(stdout, stderr, format) vulnResult, err := osvscanner.DoScan(osvscanner.ScannerActions{ LockfilePaths: context.StringSlice("lockfile"), @@ -133,7 +133,7 @@ func run(args []string, stdout, stderr io.Writer) int { if err := app.Run(args); err != nil { if r == nil { - r = output.NewReporter(stdout, stderr, "") + r = reporter.NewReporter(stdout, stderr, "") } if errors.Is(err, osvscanner.VulnerabilitiesFoundErr) { return 1 diff --git a/internal/sourceanalysis/go.go b/internal/sourceanalysis/go.go index a2a599ab07..88ae0d5d9c 100644 --- a/internal/sourceanalysis/go.go +++ b/internal/sourceanalysis/go.go @@ -5,13 +5,13 @@ import ( "path/filepath" "github.com/google/osv-scanner/internal/govulncheckshim" - "github.com/google/osv-scanner/internal/output" "github.com/google/osv-scanner/pkg/models" + "github.com/google/osv-scanner/pkg/reporter" "golang.org/x/exp/slices" "golang.org/x/vuln/exp/govulncheck" ) -func goAnalysis(r *output.Reporter, pkgs []models.PackageVulns, source models.SourceInfo) { +func goAnalysis(r *reporter.Reporter, pkgs []models.PackageVulns, source models.SourceInfo) { vulns, vulnsByID := vulnsFromAllPkgs(pkgs) res, err := govulncheckshim.RunGoVulnCheck(filepath.Dir(source.Path), vulns) if err != nil { diff --git a/internal/sourceanalysis/sourceanalysis.go b/internal/sourceanalysis/sourceanalysis.go index 121233b901..885a2d0504 100644 --- a/internal/sourceanalysis/sourceanalysis.go +++ b/internal/sourceanalysis/sourceanalysis.go @@ -3,8 +3,8 @@ package sourceanalysis import ( "path/filepath" - "github.com/google/osv-scanner/internal/output" "github.com/google/osv-scanner/pkg/models" + "github.com/google/osv-scanner/pkg/reporter" ) // vulnsFromAllPkgs returns the flattened list of unique vulnerabilities @@ -25,7 +25,7 @@ func vulnsFromAllPkgs(pkgs []models.PackageVulns) ([]models.Vulnerability, map[s } // Run runs the language specific analyzers on the code given packages and source info -func Run(r *output.Reporter, source models.SourceInfo, pkgs []models.PackageVulns) { +func Run(r *reporter.Reporter, source models.SourceInfo, pkgs []models.PackageVulns) { // GoVulnCheck if source.Type == "lockfile" && filepath.Base(source.Path) == "go.mod" { goAnalysis(r, pkgs, source) diff --git a/pkg/config/config.go b/pkg/config/config.go index 91c3226297..cf076d15a7 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -6,9 +6,8 @@ import ( "path/filepath" "time" - "github.com/google/osv-scanner/internal/output" - "github.com/BurntSushi/toml" + "github.com/google/osv-scanner/pkg/reporter" "golang.org/x/exp/slices" ) @@ -64,7 +63,7 @@ func (c *ConfigManager) UseOverride(configPath string) error { } // Attempts to get the config -func (c *ConfigManager) Get(r *output.Reporter, targetPath string) Config { +func (c *ConfigManager) Get(r *reporter.Reporter, targetPath string) Config { if c.OverrideConfig != nil { return *c.OverrideConfig } diff --git a/pkg/osvscanner/osvscanner.go b/pkg/osvscanner/osvscanner.go index c5023021c8..aadfaf0dbd 100644 --- a/pkg/osvscanner/osvscanner.go +++ b/pkg/osvscanner/osvscanner.go @@ -9,12 +9,12 @@ import ( "path/filepath" "strings" - "github.com/google/osv-scanner/internal/output" "github.com/google/osv-scanner/internal/sbom" "github.com/google/osv-scanner/pkg/config" "github.com/google/osv-scanner/pkg/lockfile" "github.com/google/osv-scanner/pkg/models" "github.com/google/osv-scanner/pkg/osv" + "github.com/google/osv-scanner/pkg/reporter" "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/osfs" @@ -52,7 +52,7 @@ var OnlyUncalledVulnerabilitiesFoundErr = errors.New("only uncalled vulnerabilit // - Any lockfiles with scanLockfile // - Any SBOM files with scanSBOMFile // - Any git repositories with scanGit -func scanDir(r *output.Reporter, query *osv.BatchedQuery, dir string, skipGit bool, recursive bool, useGitIgnore bool) error { +func scanDir(r *reporter.Reporter, query *osv.BatchedQuery, dir string, skipGit bool, recursive bool, useGitIgnore bool) error { var ignoreMatcher *gitIgnoreMatcher if useGitIgnore { var err error @@ -180,7 +180,7 @@ func (m *gitIgnoreMatcher) match(absPath string, isDir bool) (bool, error) { // scanLockfile will load, identify, and parse the lockfile path passed in, and add the dependencies specified // within to `query` -func scanLockfile(r *output.Reporter, query *osv.BatchedQuery, path string, parseAs string) error { +func scanLockfile(r *reporter.Reporter, query *osv.BatchedQuery, path string, parseAs string) error { var err error var parsedLockfile lockfile.Lockfile @@ -221,7 +221,7 @@ func scanLockfile(r *output.Reporter, query *osv.BatchedQuery, path string, pars // scanSBOMFile will load, identify, and parse the SBOM path passed in, and add the dependencies specified // within to `query` -func scanSBOMFile(r *output.Reporter, query *osv.BatchedQuery, path string) error { +func scanSBOMFile(r *reporter.Reporter, query *osv.BatchedQuery, path string) error { for _, provider := range sbom.Providers { if !provider.MatchesRecognizedFileNames(path) { // Skip if filename is not usually a sbom file of this format @@ -289,7 +289,7 @@ func getCommitSHA(repoDir string) (string, error) { } // Scan git repository. Expects repoDir to end with / -func scanGit(r *output.Reporter, query *osv.BatchedQuery, repoDir string) error { +func scanGit(r *reporter.Reporter, query *osv.BatchedQuery, repoDir string) error { commit, err := getCommitSHA(repoDir) if err != nil { return err @@ -310,7 +310,7 @@ func scanGitCommit(query *osv.BatchedQuery, commit string, source string) error return nil } -func scanDebianDocker(r *output.Reporter, query *osv.BatchedQuery, dockerImageName string) error { +func scanDebianDocker(r *reporter.Reporter, query *osv.BatchedQuery, dockerImageName string) error { cmd := exec.Command("docker", "run", "--rm", "--entrypoint", "/usr/bin/dpkg-query", dockerImageName, "-f", "${Package}###${Version}\\n", "-W") stdout, err := cmd.StdoutPipe() @@ -358,7 +358,7 @@ func scanDebianDocker(r *output.Reporter, query *osv.BatchedQuery, dockerImageNa } // Filters results according to config, preserving order. Returns total number of vulnerabilities removed. -func filterResults(r *output.Reporter, results *models.VulnerabilityResults, configManager *config.ConfigManager) int { +func filterResults(r *reporter.Reporter, results *models.VulnerabilityResults, configManager *config.ConfigManager) int { removedCount := 0 newResults := []models.PackageSource{} // Want 0 vulnerabilities to show in JSON as an empty list, not null. for _, pkgSrc := range results.Results { @@ -384,7 +384,7 @@ func filterResults(r *output.Reporter, results *models.VulnerabilityResults, con } // Filters package-grouped vulnerabilities according to config, preserving ordering. Returns filtered package vulnerabilities. -func filterPackageVulns(r *output.Reporter, pkgVulns models.PackageVulns, configToUse config.Config) models.PackageVulns { +func filterPackageVulns(r *reporter.Reporter, pkgVulns models.PackageVulns, configToUse config.Config) models.PackageVulns { ignoredVulns := map[string]struct{}{} // Iterate over groups first to remove all aliases of ignored vulnerabilities. var newGroups []models.GroupInfo @@ -441,9 +441,9 @@ func parseLockfilePath(lockfileElem string) (string, string) { } // Perform osv scanner action, with optional reporter to output information -func DoScan(actions ScannerActions, r *output.Reporter) (models.VulnerabilityResults, error) { +func DoScan(actions ScannerActions, r *reporter.Reporter) (models.VulnerabilityResults, error) { if r == nil { - r = output.NewVoidReporter() + r = reporter.NewVoidReporter() } configManager := config.ConfigManager{ diff --git a/pkg/osvscanner/osvscanner_internal_test.go b/pkg/osvscanner/osvscanner_internal_test.go index fa7f31034c..f45e38db25 100644 --- a/pkg/osvscanner/osvscanner_internal_test.go +++ b/pkg/osvscanner/osvscanner_internal_test.go @@ -5,10 +5,10 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/google/osv-scanner/internal/output" "github.com/google/osv-scanner/internal/testutility" "github.com/google/osv-scanner/pkg/config" "github.com/google/osv-scanner/pkg/models" + "github.com/google/osv-scanner/pkg/reporter" ) func Test_filterResults(t *testing.T) { @@ -51,7 +51,7 @@ func Test_filterResults(t *testing.T) { tt := tt // Reinitialize for t.Parallel() t.Run(tt.name, func(t *testing.T) { t.Parallel() - r := output.NewVoidReporter() + r := reporter.NewVoidReporter() // ConfigManager looks for osv-scanner.toml in the source path. // Sources in the test input should point to files/folders in the text fixture folder for this to work correctly. configManager := config.ConfigManager{ diff --git a/pkg/osvscanner/vulnerability_result.go b/pkg/osvscanner/vulnerability_result.go index fab5381a77..a477a5fd0f 100644 --- a/pkg/osvscanner/vulnerability_result.go +++ b/pkg/osvscanner/vulnerability_result.go @@ -4,16 +4,16 @@ import ( "fmt" "sort" - "github.com/google/osv-scanner/internal/output" "github.com/google/osv-scanner/internal/sourceanalysis" "github.com/google/osv-scanner/pkg/grouper" "github.com/google/osv-scanner/pkg/models" "github.com/google/osv-scanner/pkg/osv" + "github.com/google/osv-scanner/pkg/reporter" ) // groupResponseBySource converts raw OSV API response into structured vulnerability information // grouped by source location. -func groupResponseBySource(r *output.Reporter, query osv.BatchedQuery, resp *osv.HydratedBatchedResponse, callAnalysis bool) models.VulnerabilityResults { +func groupResponseBySource(r *reporter.Reporter, query osv.BatchedQuery, resp *osv.HydratedBatchedResponse, callAnalysis bool) models.VulnerabilityResults { output := models.VulnerabilityResults{ Results: []models.PackageSource{}, } diff --git a/pkg/osvscanner/vulnerability_result_internal_test.go b/pkg/osvscanner/vulnerability_result_internal_test.go index 79e860b7ab..212b5ff080 100644 --- a/pkg/osvscanner/vulnerability_result_internal_test.go +++ b/pkg/osvscanner/vulnerability_result_internal_test.go @@ -4,15 +4,15 @@ import ( "reflect" "testing" - "github.com/google/osv-scanner/internal/output" "github.com/google/osv-scanner/pkg/models" "github.com/google/osv-scanner/pkg/osv" + "github.com/google/osv-scanner/pkg/reporter" ) func Test_groupResponseBySource(t *testing.T) { t.Parallel() type args struct { - r *output.Reporter + r *reporter.Reporter query osv.BatchedQuery resp *osv.HydratedBatchedResponse callAnalysis bool diff --git a/internal/output/reporter.go b/pkg/reporter/reporter.go similarity index 86% rename from internal/output/reporter.go rename to pkg/reporter/reporter.go index f37234ad1e..0cf7171c6a 100644 --- a/internal/output/reporter.go +++ b/pkg/reporter/reporter.go @@ -1,10 +1,11 @@ -package output +package reporter import ( "fmt" "io" "strings" + "github.com/google/osv-scanner/internal/output" "github.com/google/osv-scanner/pkg/models" ) @@ -60,11 +61,11 @@ func (r *Reporter) PrintText(msg string) { func (r *Reporter) PrintResult(vulnResult *models.VulnerabilityResults) error { switch r.format { case "json": - return PrintJSONResults(vulnResult, r.stdout) + return output.PrintJSONResults(vulnResult, r.stdout) case "markdown": - PrintMarkdownTableResults(vulnResult, r.stdout) + output.PrintMarkdownTableResults(vulnResult, r.stdout) case "table": - PrintTableResults(vulnResult, r.stdout) + output.PrintTableResults(vulnResult, r.stdout) } return nil