internal/govulncheck: return exit code 0 for -json mode when vulns are found
When vulnerabilities are found, we return an exit code 3 if running in
text mode, because we assume that users are checking for whether
vulnerabilities exist in their code. Therefore, the presence of
vulnerabilities should be a failure, regardless of what is in the
output.
This isn't the case for -json mode, since the presence of JSON data
indicates success, so return an exit code of 0. This is consistent with
a decision from CL 432236.
Change-Id: Ie403ea79e40eb80bad590679a27ef9c3f5f8665a
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/474795
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Julie Qiu <julieqiu@google.com>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
Run-TryBot: Julie Qiu <julieqiu@google.com>
diff --git a/internal/govulncheck/print_test.go b/internal/govulncheck/print_test.go
index 048797b..97ad1b5 100644
--- a/internal/govulncheck/print_test.go
+++ b/internal/govulncheck/print_test.go
@@ -141,7 +141,7 @@
got := new(strings.Builder)
output := readableOutput{to: got}
- if err := output.result(r, false, true); err != nil {
+ if err := output.result(r, false, true); err != nil && err != ErrVulnerabilitiesFound {
t.Fatal(err)
}
want := `No vulnerabilities found.
@@ -199,7 +199,7 @@
got := new(strings.Builder)
output := readableOutput{to: got}
- if err := output.result(r, false, true); err != nil {
+ if err := output.result(r, false, true); err != nil && err != ErrVulnerabilitiesFound {
t.Fatal(err)
}
want := `Your code is affected by 1 vulnerability from 1 module.
@@ -266,7 +266,7 @@
got := new(strings.Builder)
output := readableOutput{to: got}
- if err := output.result(r, false, false); err != nil {
+ if err := output.result(r, false, false); err != nil && err != ErrVulnerabilitiesFound {
t.Fatal(err)
}
want := `Your code is affected by 2 vulnerabilities from 1 module and the Go standard library.
@@ -328,7 +328,7 @@
got := new(strings.Builder)
output := readableOutput{to: got}
- if err := output.result(r, false, true); err != nil {
+ if err := output.result(r, false, true); err != nil && err != ErrVulnerabilitiesFound {
t.Fatal(err)
}
want := `Your code is affected by 1 vulnerability from 2 modules.
diff --git a/internal/govulncheck/scan.go b/internal/govulncheck/scan.go
index 65eda61..3e531d1 100644
--- a/internal/govulncheck/scan.go
+++ b/internal/govulncheck/scan.go
@@ -155,31 +155,7 @@
if err != nil {
return err
}
- if err := out.result(res, c.verbose, c.sourceAnalysis); err != nil {
- return err
- }
-
- // Return exit status -3 if some vulnerabilities are actually
- // called in source mode or just present in binary mode.
- //
- // This follows the style from
- // golang.org/x/tools/go/analysis/singlechecker,
- // which fails with 3 if there are some findings.
- if c.sourceAnalysis {
- for _, v := range res.Vulns {
- if v.IsCalled() {
- return ErrVulnerabilitiesFound
- }
- }
- } else if len(res.Vulns) > 0 {
- return ErrVulnerabilitiesFound
- }
- return nil
-}
-
-// jsonFail prints an error to stdout in the format {Error: errorString}
-func jsonFail(err error) {
- fmt.Printf("{\"Error\": %q}\n", err)
+ return out.result(res, c.verbose, c.sourceAnalysis)
}
func isFile(path string) bool {
diff --git a/internal/govulncheck/text.go b/internal/govulncheck/text.go
index 1fd4759..2f3e5cc 100644
--- a/internal/govulncheck/text.go
+++ b/internal/govulncheck/text.go
@@ -102,7 +102,28 @@
if err != nil {
return err
}
- return tmpl.Execute(o.to, tmplRes)
+ if err := tmpl.Execute(o.to, tmplRes); err != nil {
+ return err
+ }
+
+ // Return exit status -3 if some vulnerabilities are actually
+ // called in source mode or just present in binary mode.
+ //
+ // This follows the style from
+ // golang.org/x/tools/go/analysis/singlechecker,
+ // which fails with 3 if there are some findings.
+ //
+ // TODO(https://go.dev/issue/58945): add a test for this
+ if source {
+ for _, v := range r.Vulns {
+ if v.IsCalled() {
+ return ErrVulnerabilitiesFound
+ }
+ }
+ } else if len(r.Vulns) > 0 {
+ return ErrVulnerabilitiesFound
+ }
+ return nil
}
func (o *readableOutput) progress(msg string) {