[vuln] cmd/govulncheck: fix exit code propagation for wrapped scan errors

7 views
Skip to first unread message

Ethan Lee (Gerrit)

unread,
Jun 2, 2026, 10:18:37 PMJun 2
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

Ethan Lee has uploaded the change for review

Commit message

cmd/govulncheck: fix exit code propagation for wrapped scan errors
Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6

Change diff

diff --git a/cmd/govulncheck/main.go b/cmd/govulncheck/main.go
index 73e3370..5bb6132 100644
--- a/cmd/govulncheck/main.go
+++ b/cmd/govulncheck/main.go
@@ -6,6 +6,7 @@

import (
"context"
+ "errors"
"fmt"
"os"

@@ -23,11 +24,14 @@
if err == nil {
err = cmd.Wait()
}
- switch err := err.(type) {
- case nil:
- case interface{ ExitCode() int }:
- os.Exit(err.ExitCode())
- default:
+ if err != nil {
+ var e interface{ ExitCode() int }
+ if errors.As(err, &e) {
+ if _, ok := err.(interface{ ExitCode() int }); !ok {
+ fmt.Fprintln(os.Stderr, err)
+ }
+ os.Exit(e.ExitCode())
+ }
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
diff --git a/cmd/govulncheck/main_test.go b/cmd/govulncheck/main_test.go
index 5613de5..1a19778 100644
--- a/cmd/govulncheck/main_test.go
+++ b/cmd/govulncheck/main_test.go
@@ -7,6 +7,7 @@
import (
"bytes"
"context"
+ "errors"
"flag"
"fmt"
"os"
@@ -155,16 +156,21 @@
return nil, err
}
err := cmd.Wait()
- switch e := err.(type) {
- case nil:
- case interface{ ExitCode() int }:
- err = &cmdtest.ExitCodeErr{Msg: err.Error(), Code: e.ExitCode()}
- if e.ExitCode() == 0 {
- err = nil
+ if err != nil {
+ var e interface{ ExitCode() int }
+ if errors.As(err, &e) {
+ code := e.ExitCode()
+ if _, ok := err.(interface{ ExitCode() int }); !ok {
+ fmt.Fprintln(buf, err)
+ }
+ err = &cmdtest.ExitCodeErr{Msg: err.Error(), Code: code}
+ if code == 0 {
+ err = nil
+ }
+ } else {
+ fmt.Fprintln(buf, err)
+ err = &cmdtest.ExitCodeErr{Msg: err.Error(), Code: 1}
}
- default:
- fmt.Fprintln(buf, err)
- err = &cmdtest.ExitCodeErr{Msg: err.Error(), Code: 1}
}
sorted := buf
if err == nil && isJSONMode(args) {
diff --git a/cmd/govulncheck/testdata/common/testfiles/usage/source_no_packages.ct b/cmd/govulncheck/testdata/common/testfiles/usage/source_no_packages.ct
index 27d44a9..e783d31 100644
--- a/cmd/govulncheck/testdata/common/testfiles/usage/source_no_packages.ct
+++ b/cmd/govulncheck/testdata/common/testfiles/usage/source_no_packages.ct
@@ -1,5 +1,4 @@
#####
# Test message when there are no packages matching the provided pattern (#59623).
-$ govulncheck -show verbose -C ${moddir}/vuln pkg/no-govulncheck/...
-No packages matched the provided pattern.
-No vulnerabilities found.
+$ govulncheck -show verbose -C ${moddir}/vuln pkg/no-govulncheck/... --> FAIL 2
+govulncheck: no packages matched the provided patterns
diff --git a/cmd/govulncheck/testdata/common/testfiles/usage/usage.ct b/cmd/govulncheck/testdata/common/testfiles/usage/usage.ct
index ff2c2ae..345e9b3 100644
--- a/cmd/govulncheck/testdata/common/testfiles/usage/usage.ct
+++ b/cmd/govulncheck/testdata/common/testfiles/usage/usage.ct
@@ -35,15 +35,19 @@

#####
# Not scanning anything.
-$ govulncheck
-No vulnerabilities found.
+$ govulncheck --> FAIL 2
+govulncheck: no package patterns provided
+
+To scan the current module, run: govulncheck ./...

#####
# Reporting version without scanning anything.
-$ govulncheck -version
+$ govulncheck -version --> FAIL 2
Go: go1.18
Scanner: govul...@v1.0.0
DB: testdata/vulndb-v1
DB updated: 2023-04-03 15:57:51 +0000 UTC

-No vulnerabilities found.
+govulncheck: no package patterns provided
+
+To scan the current module, run: govulncheck ./...

Change information

Files:
  • M cmd/govulncheck/main.go
  • M cmd/govulncheck/main_test.go
  • M cmd/govulncheck/testdata/common/testfiles/usage/source_no_packages.ct
  • M cmd/govulncheck/testdata/common/testfiles/usage/usage.ct
Change size: M
Delta: 4 files changed, 34 insertions(+), 21 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: vuln
Gerrit-Branch: master
Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
Gerrit-Change-Number: 786440
Gerrit-PatchSet: 1
Gerrit-Owner: Ethan Lee <etha...@google.com>
Gerrit-Reviewer: Ethan Lee <etha...@google.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Ethan Lee (Gerrit)

unread,
Jun 2, 2026, 10:21:14 PMJun 2
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com
Attention needed from Ethan Lee

Ethan Lee uploaded new patchset

Ethan Lee uploaded patch set #2 to this change.
Open in Gerrit

Related details

Attention is currently required from:
  • Ethan Lee
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newpatchset
Gerrit-Project: vuln
Gerrit-Branch: master
Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
Gerrit-Change-Number: 786440
Gerrit-PatchSet: 2
Gerrit-Owner: Ethan Lee <etha...@google.com>
Gerrit-Reviewer: Ethan Lee <etha...@google.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Ethan Lee (Gerrit)

unread,
Jun 2, 2026, 10:23:07 PMJun 2
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com
Attention needed from Ethan Lee

Ethan Lee uploaded new patchset

Ethan Lee uploaded patch set #4 to this change.
Open in Gerrit

Related details

Attention is currently required from:
  • Ethan Lee
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newpatchset
Gerrit-Project: vuln
Gerrit-Branch: master
Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
Gerrit-Change-Number: 786440
Gerrit-PatchSet: 4
Gerrit-Owner: Ethan Lee <etha...@google.com>
Gerrit-Reviewer: Ethan Lee <etha...@google.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Ethan Lee (Gerrit)

unread,
Jun 2, 2026, 10:23:24 PMJun 2
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com
Attention needed from Ethan Lee

Ethan Lee uploaded new patchset

Ethan Lee uploaded patch set #5 to this change.
Open in Gerrit

Related details

Attention is currently required from:
  • Ethan Lee
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newpatchset
Gerrit-Project: vuln
Gerrit-Branch: master
Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
Gerrit-Change-Number: 786440
Gerrit-PatchSet: 5
unsatisfied_requirement
satisfied_requirement
open
diffy

Ethan Lee (Gerrit)

unread,
Jun 2, 2026, 10:24:23 PMJun 2
to goph...@pubsubhelper.golang.org, Dmitri Shuralyov, golang...@luci-project-accounts.iam.gserviceaccount.com, golang-co...@googlegroups.com
Attention needed from Dmitri Shuralyov

Ethan Lee voted

Auto-Submit+1
Commit-Queue+1
Open in Gerrit

Related details

Attention is currently required from:
  • Dmitri Shuralyov
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: vuln
Gerrit-Branch: master
Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
Gerrit-Change-Number: 786440
Gerrit-PatchSet: 6
Gerrit-Owner: Ethan Lee <etha...@google.com>
Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
Gerrit-Attention: Dmitri Shuralyov <dmit...@golang.org>
Gerrit-Comment-Date: Wed, 03 Jun 2026 02:24:20 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
unsatisfied_requirement
satisfied_requirement
open
diffy

Ethan Lee (Gerrit)

unread,
Jun 2, 2026, 10:53:51 PMJun 2
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com
Attention needed from Dmitri Shuralyov and Ethan Lee

Ethan Lee uploaded new patchset

Ethan Lee uploaded patch set #7 to this change.
Following approvals got outdated and were removed:
Open in Gerrit

Related details

Attention is currently required from:
  • Dmitri Shuralyov
  • Ethan Lee
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newpatchset
Gerrit-Project: vuln
Gerrit-Branch: master
Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
Gerrit-Change-Number: 786440
Gerrit-PatchSet: 7
Gerrit-Owner: Ethan Lee <etha...@google.com>
Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
Gerrit-Reviewer: Ethan Lee <etha...@google.com>
Gerrit-Attention: Dmitri Shuralyov <dmit...@golang.org>
Gerrit-Attention: Ethan Lee <etha...@google.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Dmitri Shuralyov (Gerrit)

unread,
Jun 3, 2026, 11:05:36 AMJun 3
to Ethan Lee, goph...@pubsubhelper.golang.org, golang...@luci-project-accounts.iam.gserviceaccount.com, Dmitri Shuralyov, golang-co...@googlegroups.com
Attention needed from Ethan Lee

Dmitri Shuralyov added 4 comments

Patchset-level comments
File-level comment, Patchset 7 (Latest):
Dmitri Shuralyov . resolved

Thanks for working on a fix. I may not be the best reviewer for this since I'm not familiar with x/vuln and conventions or constraints involved here. I left some questions, but if there's someone better to review this, please feel free to add them.

Commit Message
Line 14, Patchset 7 (Latest):Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
Dmitri Shuralyov . unresolved

Since the original issue happens only when -short flag is left out, the signal from current trybots isn't telling us whether that issue is fixed. I suggest adding a line here that will ensure at least one longtest builder needs to pass:


```suggestion
Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
Cq-Include-Trybots: luci.golang.try:x_vuln-gotip-linux-amd64-longtest
```

(The Cq-Include-Trybots footer syntax is documented at https://go.dev/wiki/SlowBots#using-slowbots, under the 'Blocking' section.)

Or if there's more to do to beyond this CL get the longtest builders passing, you can leave this out and use 'For' instead of 'Fixes'.

File cmd/govulncheck/main.go
Line 36, Patchset 7 (Latest): os.Exit(1)
Dmitri Shuralyov . unresolved

A few questions about this error handling logic. It seems a bit complicated, and I'm not sure if that complexity is required or can be avoided.

I haven't encountered errors.As used with an interface type as the target. (Compare with the examples at https://pkg.go.dev/errors#As that show struct types.) What's the reason both errors.As and a type assertion are both used? Could this be simplified to an unconditional print to stderr and single type assertion instead, something like:

```
fmt.Fprintln(os.Stderr, err)
if e, ok := err.(interface{ ExitCode() int}); ok {
os.Exit(e.ExitCode())
} else {
os.Exit(1)
}
```

Or is the reason errors.As needs to be used because `err` itself may be wrapped in a way that hides the ExitCode method at the top level, such that the type assertion to the interface fails, yet errors.As unwraps the error and finds that something in its tree matches?

(Part of the reason I can't tell what is intended here is that the scan.Cmd.Wait API doesn't talk about how it reports errors and exit codes; see another inline comment about that.)

File scan/scan.go
Open in Gerrit

Related details

Attention is currently required from:
  • Ethan Lee
Submit Requirements:
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: vuln
    Gerrit-Branch: master
    Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
    Gerrit-Change-Number: 786440
    Gerrit-PatchSet: 7
    Gerrit-Owner: Ethan Lee <etha...@google.com>
    Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
    Gerrit-Reviewer: Ethan Lee <etha...@google.com>
    Gerrit-Attention: Ethan Lee <etha...@google.com>
    Gerrit-Comment-Date: Wed, 03 Jun 2026 15:05:32 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    unsatisfied_requirement
    satisfied_requirement
    open
    diffy

    Ethan Lee (Gerrit)

    unread,
    Jun 15, 2026, 4:07:00 PMJun 15
    to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com
    Attention needed from Ethan Lee

    Ethan Lee uploaded new patchset

    Ethan Lee uploaded patch set #8 to this change.
    Following approvals got outdated and were removed:

    Related details

    Attention is currently required from:
    • Ethan Lee
    Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement is not satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: newpatchset
      Gerrit-Project: vuln
      Gerrit-Branch: master
      Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
      Gerrit-Change-Number: 786440
      Gerrit-PatchSet: 8
      unsatisfied_requirement
      open
      diffy

      Ethan Lee (Gerrit)

      unread,
      Jun 15, 2026, 4:07:05 PMJun 15
      to goph...@pubsubhelper.golang.org, golang...@luci-project-accounts.iam.gserviceaccount.com, Dmitri Shuralyov, golang-co...@googlegroups.com
      Attention needed from Dmitri Shuralyov

      Ethan Lee added 3 comments

      Commit Message
      Line 14, Patchset 7:Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
      Dmitri Shuralyov . resolved

      Since the original issue happens only when -short flag is left out, the signal from current trybots isn't telling us whether that issue is fixed. I suggest adding a line here that will ensure at least one longtest builder needs to pass:


      ```suggestion
      Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
      Cq-Include-Trybots: luci.golang.try:x_vuln-gotip-linux-amd64-longtest
      ```

      (The Cq-Include-Trybots footer syntax is documented at https://go.dev/wiki/SlowBots#using-slowbots, under the 'Blocking' section.)

      Or if there's more to do to beyond this CL get the longtest builders passing, you can leave this out and use 'For' instead of 'Fixes'.

      Ethan Lee

      Interesting! Thanks for letting me know about this format. :) Done.

      File cmd/govulncheck/main.go
      Dmitri Shuralyov . unresolved

      A few questions about this error handling logic. It seems a bit complicated, and I'm not sure if that complexity is required or can be avoided.

      I haven't encountered errors.As used with an interface type as the target. (Compare with the examples at https://pkg.go.dev/errors#As that show struct types.) What's the reason both errors.As and a type assertion are both used? Could this be simplified to an unconditional print to stderr and single type assertion instead, something like:

      ```
      fmt.Fprintln(os.Stderr, err)
      if e, ok := err.(interface{ ExitCode() int}); ok {
      os.Exit(e.ExitCode())
      } else {
      os.Exit(1)
      }
      ```

      Or is the reason errors.As needs to be used because `err` itself may be wrapped in a way that hides the ExitCode method at the top level, such that the type assertion to the interface fails, yet errors.As unwraps the error and finds that something in its tree matches?

      (Part of the reason I can't tell what is intended here is that the scan.Cmd.Wait API doesn't talk about how it reports errors and exit codes; see another inline comment about that.)

      Ethan Lee

      Your second reason is correct.

      `errors.As(err, &e)` is used to retrieve the exit code from nested errors (e.g., wrapped via `fmt.Errorf("context: %w", ...)`). A simple type assertion `err.(interface{ ExitCode() int })` at the top level would fail on wrapped errors, masking the actual exit code (such as exiting with 1 instead of 3 for vulnerabilities).

      We also want to prevent duplicate logging. We can't unconditionally print to stderr because some exit-code errors are silent (like errVulnerabilitiesFound with exit code 3, or errHelp with exit code 0).

      I addressed the other comment with appropriate documentation. Let me know if that's clear.

      File scan/scan.go
      Open in Gerrit

      Related details

      Attention is currently required from:
      • Dmitri Shuralyov
      Submit Requirements:
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement is not satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: vuln
      Gerrit-Branch: master
      Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
      Gerrit-Change-Number: 786440
      Gerrit-PatchSet: 8
      Gerrit-Owner: Ethan Lee <etha...@google.com>
      Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
      Gerrit-Reviewer: Ethan Lee <etha...@google.com>
      Gerrit-Attention: Dmitri Shuralyov <dmit...@golang.org>
      Gerrit-Comment-Date: Mon, 15 Jun 2026 20:07:02 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Dmitri Shuralyov <dmit...@golang.org>
      unsatisfied_requirement
      open
      diffy

      Dmitri Shuralyov (Gerrit)

      unread,
      Jun 17, 2026, 9:51:41 AMJun 17
      to Ethan Lee, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, golang...@luci-project-accounts.iam.gserviceaccount.com, golang-co...@googlegroups.com
      Attention needed from Ethan Lee

      Dmitri Shuralyov voted and added 5 comments

      Votes added by Dmitri Shuralyov

      Code-Review+2

      5 comments

      Patchset-level comments
      File-level comment, Patchset 8 (Latest):
      Dmitri Shuralyov . resolved

      Thanks.

      Commit Message
      Line 14, Patchset 7:Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
      Dmitri Shuralyov . resolved

      Since the original issue happens only when -short flag is left out, the signal from current trybots isn't telling us whether that issue is fixed. I suggest adding a line here that will ensure at least one longtest builder needs to pass:


      ```suggestion
      Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
      Cq-Include-Trybots: luci.golang.try:x_vuln-gotip-linux-amd64-longtest
      ```

      (The Cq-Include-Trybots footer syntax is documented at https://go.dev/wiki/SlowBots#using-slowbots, under the 'Blocking' section.)

      Or if there's more to do to beyond this CL get the longtest builders passing, you can leave this out and use 'For' instead of 'Fixes'.

      Ethan Lee

      Interesting! Thanks for letting me know about this format. :) Done.

      Dmitri Shuralyov

      Thanks.

      It seems to be catching that TestCommand/common is still failing. If there's more work needed to get everything passing and you prefer to make that a separate CL, then it'd make sense to switch 'For' to 'Fixes'. Up to you.

      File cmd/govulncheck/main.go
      Line 31, Patchset 8 (Latest): fmt.Fprintln(os.Stderr, err)
      Dmitri Shuralyov . unresolved

      The logic of checking whether err wraps an exit code error, and whether that error is at the top of the error stack or in the middle is a bit complex, so a clarifying comment can help make this code more readable. Maybe something like:

      ```suggestion
      // If the exit code error was wrapped with another error on top, print full error details to stderr.
      // We avoid doing this if it wasn't wrapped since printing a generic "exit code n" message to stderr since is considered unhelpful.
      fmt.Fprintln(os.Stderr, err)
      ```

      Perhaps better yet use a named intermediate variable:

      ```
      printErrorToStderr := true
      if _, ok := err.(interface{ ExitCode() int }); ok {
      // Avoid printing the error to stderr if the exit code error wasn't
      // wrapped with another error providing context.
      printErrorToStderr = false
      }
      if printErrorToStderr {
      fmt.Fprintln(os.Stderr, err)
      }
      ```
      Dmitri Shuralyov . resolved

      A few questions about this error handling logic. It seems a bit complicated, and I'm not sure if that complexity is required or can be avoided.

      I haven't encountered errors.As used with an interface type as the target. (Compare with the examples at https://pkg.go.dev/errors#As that show struct types.) What's the reason both errors.As and a type assertion are both used? Could this be simplified to an unconditional print to stderr and single type assertion instead, something like:

      ```
      fmt.Fprintln(os.Stderr, err)
      if e, ok := err.(interface{ ExitCode() int}); ok {
      os.Exit(e.ExitCode())
      } else {
      os.Exit(1)
      }
      ```

      Or is the reason errors.As needs to be used because `err` itself may be wrapped in a way that hides the ExitCode method at the top level, such that the type assertion to the interface fails, yet errors.As unwraps the error and finds that something in its tree matches?

      (Part of the reason I can't tell what is intended here is that the scan.Cmd.Wait API doesn't talk about how it reports errors and exit codes; see another inline comment about that.)

      Ethan Lee

      Your second reason is correct.

      `errors.As(err, &e)` is used to retrieve the exit code from nested errors (e.g., wrapped via `fmt.Errorf("context: %w", ...)`). A simple type assertion `err.(interface{ ExitCode() int })` at the top level would fail on wrapped errors, masking the actual exit code (such as exiting with 1 instead of 3 for vulnerabilities).

      We also want to prevent duplicate logging. We can't unconditionally print to stderr because some exit-code errors are silent (like errVulnerabilitiesFound with exit code 3, or errHelp with exit code 0).

      I addressed the other comment with appropriate documentation. Let me know if that's clear.

      Dmitri Shuralyov

      Thanks for clarifying.

      File cmd/govulncheck/main_test.go
      Line 163, Patchset 8 (Latest): if _, ok := err.(interface{ ExitCode() int }); !ok {
      Dmitri Shuralyov . unresolved

      Similar suggestion here as in cmd/govulncheck/main.go.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Ethan Lee
      Submit Requirements:
      • requirement satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement is not satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: vuln
      Gerrit-Branch: master
      Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
      Gerrit-Change-Number: 786440
      Gerrit-PatchSet: 8
      Gerrit-Owner: Ethan Lee <etha...@google.com>
      Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
      Gerrit-Reviewer: Ethan Lee <etha...@google.com>
      Gerrit-Attention: Ethan Lee <etha...@google.com>
      Gerrit-Comment-Date: Wed, 17 Jun 2026 13:51:36 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: Yes
      Comment-In-Reply-To: Dmitri Shuralyov <dmit...@golang.org>
      Comment-In-Reply-To: Ethan Lee <etha...@google.com>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Dmitri Shuralyov (Gerrit)

      unread,
      Jun 17, 2026, 9:52:08 AMJun 17
      to Ethan Lee, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, golang...@luci-project-accounts.iam.gserviceaccount.com, golang-co...@googlegroups.com
      Attention needed from Ethan Lee

      Dmitri Shuralyov voted Code-Review+1

      Code-Review+1
      Open in Gerrit

      Related details

      Attention is currently required from:
      • Ethan Lee
      Submit Requirements:
        • requirement satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement satisfiedReview-Enforcement
        • requirement is not satisfiedTryBots-Pass
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: vuln
        Gerrit-Branch: master
        Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
        Gerrit-Change-Number: 786440
        Gerrit-PatchSet: 8
        Gerrit-Owner: Ethan Lee <etha...@google.com>
        Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
        Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
        Gerrit-Comment-Date: Wed, 17 Jun 2026 13:52:02 +0000
        Gerrit-HasComments: No
        Gerrit-Has-Labels: Yes
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Ethan Lee (Gerrit)

        unread,
        Jun 17, 2026, 2:44:03 PMJun 17
        to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com
        Attention needed from Dmitri Shuralyov, Dmitri Shuralyov and Ethan Lee

        Ethan Lee uploaded new patchset

        Ethan Lee uploaded patch set #9 to this change.
        Following approvals got outdated and were removed:
        Open in Gerrit

        Related details

        Attention is currently required from:
        • Dmitri Shuralyov
        • Dmitri Shuralyov
        • Ethan Lee
        Submit Requirements:
        • requirement is not satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement is not satisfiedReview-Enforcement
        • requirement is not satisfiedTryBots-Pass
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: newpatchset
        Gerrit-Project: vuln
        Gerrit-Branch: master
        Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
        Gerrit-Change-Number: 786440
        Gerrit-PatchSet: 9
        Gerrit-Owner: Ethan Lee <etha...@google.com>
        Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
        Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
        Gerrit-Reviewer: Ethan Lee <etha...@google.com>
        Gerrit-Attention: Dmitri Shuralyov <dmit...@google.com>
        unsatisfied_requirement
        open
        diffy

        Ethan Lee (Gerrit)

        unread,
        Jun 17, 2026, 2:44:23 PMJun 17
        to goph...@pubsubhelper.golang.org, Dmitri Shuralyov, Dmitri Shuralyov, golang...@luci-project-accounts.iam.gserviceaccount.com, golang-co...@googlegroups.com
        Attention needed from Dmitri Shuralyov and Dmitri Shuralyov

        Ethan Lee added 3 comments

        Patchset-level comments
        File-level comment, Patchset 9 (Latest):
        Ethan Lee . resolved

        kokoro rerun

        File cmd/govulncheck/main.go
        Line 31, Patchset 8: fmt.Fprintln(os.Stderr, err)
        Dmitri Shuralyov . resolved

        The logic of checking whether err wraps an exit code error, and whether that error is at the top of the error stack or in the middle is a bit complex, so a clarifying comment can help make this code more readable. Maybe something like:

        ```suggestion
        // If the exit code error was wrapped with another error on top, print full error details to stderr.
        // We avoid doing this if it wasn't wrapped since printing a generic "exit code n" message to stderr since is considered unhelpful.
        fmt.Fprintln(os.Stderr, err)
        ```

        Perhaps better yet use a named intermediate variable:

        ```
        printErrorToStderr := true
        if _, ok := err.(interface{ ExitCode() int }); ok {
        // Avoid printing the error to stderr if the exit code error wasn't
        // wrapped with another error providing context.
        printErrorToStderr = false
        }
        if printErrorToStderr {
        fmt.Fprintln(os.Stderr, err)
        }
        ```
        Ethan Lee

        Done

        File cmd/govulncheck/main_test.go
        Line 163, Patchset 8: if _, ok := err.(interface{ ExitCode() int }); !ok {
        Dmitri Shuralyov . resolved

        Similar suggestion here as in cmd/govulncheck/main.go.

        Ethan Lee

        Done

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Dmitri Shuralyov
        • Dmitri Shuralyov
        Submit Requirements:
          • requirement is not satisfiedCode-Review
          • requirement satisfiedNo-Unresolved-Comments
          • requirement is not satisfiedReview-Enforcement
          • requirement is not satisfiedTryBots-Pass
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: comment
          Gerrit-Project: vuln
          Gerrit-Branch: master
          Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
          Gerrit-Change-Number: 786440
          Gerrit-PatchSet: 9
          Gerrit-Owner: Ethan Lee <etha...@google.com>
          Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
          Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
          Gerrit-Reviewer: Ethan Lee <etha...@google.com>
          Gerrit-Attention: Dmitri Shuralyov <dmit...@google.com>
          Gerrit-Attention: Dmitri Shuralyov <dmit...@golang.org>
          Gerrit-Comment-Date: Wed, 17 Jun 2026 18:44:19 +0000
          unsatisfied_requirement
          satisfied_requirement
          open
          diffy

          Dmitri Shuralyov (Gerrit)

          unread,
          Jun 17, 2026, 2:56:03 PMJun 17
          to Ethan Lee, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, Dmitri Shuralyov, golang...@luci-project-accounts.iam.gserviceaccount.com, golang-co...@googlegroups.com
          Attention needed from Dmitri Shuralyov and Ethan Lee

          Dmitri Shuralyov voted and added 1 comment

          Votes added by Dmitri Shuralyov

          Code-Review+2

          1 comment

          Patchset-level comments
          Dmitri Shuralyov . resolved

          Thanks.

          Open in Gerrit

          Related details

          Attention is currently required from:
          • Dmitri Shuralyov
          • Ethan Lee
          Submit Requirements:
          • requirement satisfiedCode-Review
          • requirement satisfiedNo-Unresolved-Comments
          • requirement is not satisfiedReview-Enforcement
          • requirement is not satisfiedTryBots-Pass
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: comment
          Gerrit-Project: vuln
          Gerrit-Branch: master
          Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
          Gerrit-Change-Number: 786440
          Gerrit-PatchSet: 9
          Gerrit-Owner: Ethan Lee <etha...@google.com>
          Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
          Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
          Gerrit-Reviewer: Ethan Lee <etha...@google.com>
          Gerrit-Attention: Dmitri Shuralyov <dmit...@google.com>
          Gerrit-Attention: Ethan Lee <etha...@google.com>
          Gerrit-Comment-Date: Wed, 17 Jun 2026 18:55:58 +0000
          Gerrit-HasComments: Yes
          Gerrit-Has-Labels: Yes
          satisfied_requirement
          unsatisfied_requirement
          open
          diffy

          Dmitri Shuralyov (Gerrit)

          unread,
          Jun 17, 2026, 2:56:28 PMJun 17
          to Ethan Lee, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, golang...@luci-project-accounts.iam.gserviceaccount.com, golang-co...@googlegroups.com
          Attention needed from Ethan Lee

          Dmitri Shuralyov voted Code-Review+1

          Code-Review+1
          Open in Gerrit

          Related details

          Attention is currently required from:
          • Ethan Lee
          Submit Requirements:
            • requirement satisfiedCode-Review
            • requirement satisfiedNo-Unresolved-Comments
            • requirement satisfiedReview-Enforcement
            • requirement is not satisfiedTryBots-Pass
            Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
            Gerrit-MessageType: comment
            Gerrit-Project: vuln
            Gerrit-Branch: master
            Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
            Gerrit-Change-Number: 786440
            Gerrit-PatchSet: 9
            Gerrit-Owner: Ethan Lee <etha...@google.com>
            Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
            Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
            Gerrit-Reviewer: Ethan Lee <etha...@google.com>
            Gerrit-Attention: Ethan Lee <etha...@google.com>
            Gerrit-Comment-Date: Wed, 17 Jun 2026 18:56:25 +0000
            Gerrit-HasComments: No
            Gerrit-Has-Labels: Yes
            satisfied_requirement
            unsatisfied_requirement
            open
            diffy

            Ethan Lee (Gerrit)

            unread,
            Jun 17, 2026, 2:58:10 PMJun 17
            to goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, golang...@luci-project-accounts.iam.gserviceaccount.com, Dmitri Shuralyov, Dmitri Shuralyov, golang-co...@googlegroups.com

            Ethan Lee submitted the change

            Change information

            Commit message:
            cmd/govulncheck: fix exit code propagation for wrapped scan errors

            Previously, exit codes were masked improperly. Ensure that the original
            error codes are propagated.

            Fixes golang/go#78694
            Cq-Include-Trybots: luci.golang.try:x_vuln-gotip-linux-amd64-longtest
            Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
            Auto-Submit: Ethan Lee <etha...@google.com>
            Reviewed-by: Dmitri Shuralyov <dmit...@golang.org>
            Reviewed-by: Dmitri Shuralyov <dmit...@google.com>
            Files:
            • M cmd/govulncheck/main.go
            • M cmd/govulncheck/main_test.go
            • M cmd/govulncheck/testdata/common/testfiles/usage/format.ct
            • M cmd/govulncheck/testdata/common/testfiles/usage/source_no_packages.ct
            • M cmd/govulncheck/testdata/common/testfiles/usage/usage.ct
            • M internal/scan/run.go
            • M scan/scan.go
            Change size: L
            Delta: 7 files changed, 297 insertions(+), 26 deletions(-)
            Branch: refs/heads/master
            Submit Requirements:
            Open in Gerrit
            Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
            Gerrit-MessageType: merged
            Gerrit-Project: vuln
            Gerrit-Branch: master
            Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
            Gerrit-Change-Number: 786440
            Gerrit-PatchSet: 10
            open
            diffy
            satisfied_requirement

            Dustin Turner (Gerrit)

            unread,
            1:08 AM (5 hours ago) 1:08 AM
            to Ethan Lee, goph...@pubsubhelper.golang.org, golang...@luci-project-accounts.iam.gserviceaccount.com, Dmitri Shuralyov, Dmitri Shuralyov, golang-co...@googlegroups.com

            Dustin Turner voted Code-Review+1

            Code-Review+1
            Open in Gerrit

            Related details

            Attention set is empty
            Submit Requirements:
            • requirement satisfiedCode-Review
            • requirement satisfiedNo-Unresolved-Comments
            • requirement satisfiedReview-Enforcement
            • requirement satisfiedTryBots-Pass
            Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
            Gerrit-MessageType: comment
            Gerrit-Project: vuln
            Gerrit-Branch: master
            Gerrit-Change-Id: Id94878d231272a9a37817ece747692a1ad539cc6
            Gerrit-Change-Number: 786440
            Gerrit-PatchSet: 10
            Gerrit-Owner: Ethan Lee <etha...@google.com>
            Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
            Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
            Gerrit-Reviewer: Dustin Turner <dustin.t...@gmail.com>
            Gerrit-Comment-Date: Mon, 10 Aug 2026 05:08:22 +0000
            Gerrit-HasComments: No
            Gerrit-Has-Labels: Yes
            satisfied_requirement
            open
            diffy
            Reply all
            Reply to author
            Forward
            0 new messages