Skip to content

fix(ci): a real gosec finding aborts its own SARIF merge under set -e and surfaces as a missing-file error #1717

Description

@cristim

The Run gosec Security Scanner step in .github/workflows/ci.yml loops over modules under set -e. gosec exits non-zero when it finds issues, so the first genuine finding aborts the loop before the per-module SARIF files are merged. The upload step then fails with:

Path does not exist: gosec-results.sarif

So the observable symptom of gosec finding a real HIGH severity issue is a missing-file error pointing at the upload step, not a security finding. A reader is likely to read that as flaky infrastructure and re-run the job, which will fail identically.

Why it has never been seen

gosec has been clean, so the loop has never aborted. The failure mode is latent and only appears the first time gosec finds something — precisely the moment the signal matters most.

Relationship to #1712

This is the same failure shape as the npm-audit coupling fixed in #1716: a real security finding surfacing as a missing-SARIF error attributable to the wrong cause. #1716 fixed the inter-step coupling, so one scanner's failure no longer skips the others. This is the intra-step case: the scanner's own non-zero exit aborts its own merge.

#1716's if: always() && steps.<id>.outcome != 'skipped' on the upload does not help here, because the step did run — it just never reached the merge, so the file is genuinely absent.

Deliberately left out of #1716 as out of scope for that issue, and flagged in its PR body rather than fixed by restructuring gosec's error handling inside an unrelated change.

Suggested fix

Let the loop finish and merge the SARIF regardless of gosec's exit status, then fail the step on the recorded status after the merge, so the findings are uploaded and visible in GitHub Security rather than lost. Options: collect the per-module exit codes and re-raise after merging, or run the loop body with || true while capturing status explicitly.

The requirement is that a gosec finding must (a) still fail the job and (b) still upload its SARIF, so the failure names the finding rather than a missing file.

Do not make gosec's non-zero exit non-fatal without preserving the failure. Masking CI debt is prohibited in this repo, and the point is to make a real finding legible, not quieter.

Verify with a deliberately introduced gosec finding on a scratch branch: confirm the job fails, the SARIF uploads, and the annotation names the finding rather than a missing path. Do not verify by reading the YAML alone; #1716 established that these if:/set -e interactions are worth executing under act.

Found by the implementer of #1716 while fixing #1712.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions