Skip to content

Commit 6c85875

Browse files
committed
ci: wire govulncheck job to the action (missed in prior commit)
The previous commit deleted the wrapper files but a failed `git add` pathspec dropped the security.yml/CODEOWNERS/docs edits, leaving the job pointing at the now-deleted wrapper. This commits the actual govulncheck-action + SARIF-upload job body and the doc/CODEOWNERS updates.
1 parent 112fa50 commit 6c85875

3 files changed

Lines changed: 63 additions & 51 deletions

File tree

.github/CODEOWNERS

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ api/ @shellhub-io/backend-owners
33
ssh/ @shellhub-io/backend-owners
44
ui/ @shellhub-io/frontend-owners
55

6-
# Security allowlist and scanner ignore files — reviewed by team lead.
6+
# Security scanner ignore files — reviewed by team lead.
77
.trivyignore @shellhub-io/team-lead
8-
.govulncheck-allow.txt @shellhub-io/team-lead
98
.semgrepignore @shellhub-io/team-lead

.github/workflows/security.yml

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,45 +29,59 @@ jobs:
2929
matrix:
3030
include:
3131
- module: .
32-
extra_args: ""
32+
sarif_name: root
33+
tags: ""
3334
- module: api
34-
extra_args: ""
35+
sarif_name: api
36+
tags: ""
37+
# agent/ssh build-tag coverage relies on GOFLAGS being forwarded to go/packages
3538
- module: agent
36-
extra_args: "-tags docker"
39+
sarif_name: agent
40+
tags: docker
3741
- module: ssh
38-
extra_args: "-tags internal_api"
42+
sarif_name: ssh
43+
tags: internal_api
3944
- module: cli
40-
extra_args: ""
45+
sarif_name: cli
46+
tags: ""
4147
- module: gateway
42-
extra_args: ""
48+
sarif_name: gateway
49+
tags: ""
4350
- module: openapi
44-
extra_args: ""
51+
sarif_name: openapi
52+
tags: ""
4553
- module: tests
46-
extra_args: ""
54+
sarif_name: tests
55+
tags: ""
4756

4857
runs-on: ubuntu-latest
4958

5059
steps:
5160
- name: Check out code
5261
uses: actions/checkout@v6
5362

54-
- name: Set up Go
55-
uses: actions/setup-go@v6
56-
with:
57-
go-version-file: go.mod
58-
59-
- name: Install govulncheck
60-
run: go install golang.org/x/vuln/cmd/govulncheck@latest
61-
62-
- name: Build govulncheck wrapper
63-
run: |
64-
( cd "$GITHUB_WORKSPACE/.github" && go build -o "$RUNNER_TEMP/govulncheck-filter" ./govulncheck/cmd )
65-
6663
- name: Run govulncheck
67-
run: |
68-
cd "${{ matrix.module }}"
69-
govulncheck -json ${{ matrix.extra_args }} ./... | \
70-
"$RUNNER_TEMP/govulncheck-filter" "$GITHUB_WORKSPACE/.govulncheck-allow.txt"
64+
uses: golang/govulncheck-action@v1
65+
env:
66+
# govulncheck honors GOFLAGS through go/packages for build-tag coverage
67+
GOFLAGS: ${{ matrix.tags != '' && format('-tags={0}', matrix.tags) || '' }}
68+
with:
69+
go-version-file: ${{ matrix.module == '.' && 'go.mod' || format('{0}/go.mod', matrix.module) }}
70+
work-dir: ${{ matrix.module }}
71+
go-package: ./...
72+
output-format: sarif
73+
output-file: govulncheck-${{ matrix.sarif_name }}.sarif
74+
repo-checkout: false
75+
76+
# Vuln gating is performed by GitHub's native "Code scanning results" PR check
77+
# (identical to CodeQL/Semgrep); this upload step is the success signal for
78+
# security-gate — govulncheck's own exit code does NOT block the PR.
79+
- name: Upload SARIF report
80+
if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }}
81+
uses: github/codeql-action/upload-sarif@v3
82+
with:
83+
sarif_file: govulncheck-${{ matrix.sarif_name }}.sarif
84+
category: govulncheck-${{ matrix.sarif_name }}
7185

7286
trivy-image:
7387
name: trivy-image (${{ matrix.image }})

SECURITY-SCANNING.md

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ all three `security-gate` jobs report success (or skipped).
3232

3333
| Workflow file | Tool | What it scans | Runs on |
3434
|---|---|---|---|
35-
| `.github/workflows/security.yml` | **govulncheck** | Known Go CVEs in all modules (`.`, `api`, `agent`, `ssh`, `cli`, `gateway`, `openapi`, `tests`) | PR + push to master + weekly |
35+
| `.github/workflows/security.yml` | **govulncheck** | Known Go CVEs in all modules (`.`, `api`, `agent`, `ssh`, `cli`, `gateway`, `openapi`, `tests`); SARIF uploaded to GitHub Security tab | PR + push to master + weekly |
3636
| `.github/workflows/security.yml` | **Trivy (image)** | OS/library CVEs in service images (`api`, `ssh`, `gateway`, `cli`, `ui`, `agent`) | PR + push to master + weekly |
3737
| `.github/workflows/semgrep.yml` | **Semgrep** | Static analysis via `p/golang`, `p/dockerfile`, `p/ci`; PR mode uses `--baseline-ref` so only _new_ findings block | PR + push to master + weekly |
3838
| `.github/workflows/codeql.yml` | **CodeQL** | Semantic Go analysis across all modules; SARIF uploaded to GitHub Security tab | PR + push to master + weekly |
@@ -45,7 +45,7 @@ those lack the necessary `security-events: write` permission).
4545

4646
## Baseline suppression files
4747

48-
Three baseline files gate new suppressions behind a team-lead code-owner review
48+
Two baseline files gate new suppressions behind a team-lead code-owner review
4949
(see `.github/CODEOWNERS`).
5050

5151
### `.trivyignore` — Trivy CVE suppression
@@ -64,22 +64,6 @@ Three baseline files gate new suppressions behind a team-lead code-owner review
6464
`@shellhub-io/team-lead` for mandatory review.
6565
4. Schedule a quarterly review to remove the entry once the vulnerability is patched.
6666

67-
### `.govulncheck-allow.txt` — govulncheck allowlist
68-
69-
```
70-
# GO-YYYY-NNNN reachability=called|imported # owner: @handle — justification; tracked: ISSUE-123
71-
```
72-
73-
Fields:
74-
75-
- `GO-YYYY-NNNN` — Go vulnerability database ID (required).
76-
- `reachability=called` — the vulnerable function appears in the call graph.
77-
- `reachability=imported` — the vulnerable package is imported but the function is not called.
78-
79-
**How to add an entry:** follow the same owner + justification + quarterly-review process as
80-
`.trivyignore`. Stale entries (where the vulnerability no longer appears in findings) cause
81-
CI to fail — remove them promptly.
82-
8367
### `.semgrepignore` — Semgrep path exclusion
8468

8569
```
@@ -93,7 +77,7 @@ generated mocks). **Do not suppress production source paths** — fix the findi
9377

9478
## Inline suppression conventions
9579

96-
### `#nosec` (gosec / govulncheck)
80+
### `#nosec` (gosec)
9781

9882
Append `//nolint:gosec` or `#nosec GXXX` directly on the line that triggers the finding:
9983

@@ -103,6 +87,20 @@ conn, err := tls.Dial("tcp", addr, cfg) //nolint:gosec // G402: minimum TLS vers
10387

10488
Always include a short rationale after the directive.
10589

90+
### govulncheck — suppressing a finding
91+
92+
govulncheck findings are surfaced as alerts in the GitHub Security tab (SARIF-based).
93+
To suppress a known, accepted vulnerability:
94+
95+
1. Open the alert in the **Security → Code scanning alerts** tab.
96+
2. Click **Dismiss alert** and choose a reason (e.g. "Used in tests", "Risk accepted",
97+
"False positive") along with a brief comment identifying the owner and justification.
98+
3. Dismissed alerts are audited and visible to the team in the Security tab. There is no
99+
separate suppression file — suppression lives entirely in GitHub code scanning.
100+
101+
> **Note:** The `agent` and `ssh` modules scan with build tags (`docker` and `internal_api`
102+
> respectively) via the `GOFLAGS` environment variable forwarded to `go/packages`.
103+
106104
### `# nosemgrep: <rule-id> -- <reason>` (Semgrep)
107105

108106
Add a comment on the line **above** the offending code using the exact format
@@ -161,10 +159,11 @@ branch or workflow:
161159
do not yet mark them as required checks in branch protection. Let the scans accumulate
162160
data for at least one week.
163161

164-
2. **Seed the baseline files** — review findings from step 1 and populate `.trivyignore`,
165-
`.govulncheck-allow.txt`, and `.semgrepignore` with justified suppressions for any
166-
pre-existing issues that cannot be fixed immediately. Each entry requires an owner and
167-
justification comment.
162+
2. **Seed the baseline files** — review findings from step 1 and populate `.trivyignore`
163+
and `.semgrepignore` with justified suppressions for any pre-existing issues that cannot
164+
be fixed immediately. Each entry requires an owner and justification comment. For
165+
govulncheck findings, dismiss the alert in the GitHub Security tab with a reason — no
166+
separate file is needed.
168167

169168
3. **Flip to blocking-on-new** — configure Semgrep to run with `--baseline-ref origin/master`
170169
on PRs (already the default in `semgrep.yml`) so that only _new_ findings introduced by
@@ -175,7 +174,7 @@ branch or workflow:
175174
GitHub repository settings → Branches → Branch protection rules for `master`:
176175
- Under "Require status checks to pass before merging", add **`security-gate`** (the
177176
exact frozen name) from each of the three workflows (Security, Semgrep, CodeQL).
178-
- Enable **"Require review from Code Owners"** so that changes to `.trivyignore`,
179-
`.govulncheck-allow.txt`, and `.semgrepignore` always go through `@shellhub-io/team-lead`.
177+
- Enable **"Require review from Code Owners"** so that changes to `.trivyignore`
178+
and `.semgrepignore` always go through `@shellhub-io/team-lead`.
180179

181180
> **Note:** Steps 1–3 are performed by contributors; step 4 requires a repository admin.

0 commit comments

Comments
 (0)