Skip to content

Commit 7b8c2ae

Browse files
insomniusclaude
andcommitted
ci: add Tier 1 security pipelines (govulncheck, CodeQL, Trivy)
The existing CI gates (lint + test + coverage) catch correctness defects but not external risk: known CVEs in deps, source-level injection patterns, OS-package CVEs in the published Docker image. Adds three independent pipelines for those failure modes. - .github/workflows/govulncheck.yml — Go's official vulnerability scanner, runs govulncheck ./... over source + go.mod and reports only CVEs that the call graph actually reaches. Triggers on push, PR, and Friday cron. - .github/workflows/codeql.yml — GitHub-native SAST. security-and- quality query suite. Results land in the Security tab and as PR annotations. Same trigger cadence. - .github/workflows/trivy.yml — scans the published Docker image (alpine + altair binary) for HIGH/CRITICAL OS-level CVEs. Output goes to the Security tab as SARIF; doesn't fail the build initially (ignore-unfixed=true, exit-code=0) so humans can triage. Flip both knobs once the team is comfortable. Each is a separate workflow rather than a job inside general.yml so that (a) failures don't block correctness PRs, (b) cadences can diverge, (c) Security-tab routing stays clean per analyzer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 764b7cf commit 7b8c2ae

3 files changed

Lines changed: 167 additions & 0 deletions

File tree

.github/workflows/codeql.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: CodeQL
2+
3+
# GitHub's native SAST. Free for public repos. Catches injection patterns,
4+
# unsafe deserialization, hardcoded credentials, etc. Results show in the
5+
# Security tab and as PR annotations.
6+
#
7+
# Runs ~3-5 minutes; long enough to make weekly + push the right cadence
8+
# rather than per-PR (which would block merges on a slow analyzer).
9+
10+
on:
11+
push:
12+
branches: [master]
13+
pull_request:
14+
branches: [master]
15+
schedule:
16+
- cron: '0 13 * * 5'
17+
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.ref }}
20+
cancel-in-progress: true
21+
22+
permissions:
23+
actions: read
24+
contents: read
25+
security-events: write
26+
27+
jobs:
28+
analyze:
29+
name: Analyze (Go)
30+
runs-on: ubuntu-latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
- uses: actions/setup-go@v5
34+
with:
35+
go-version: stable
36+
check-latest: true
37+
cache: true
38+
39+
- name: Initialize CodeQL
40+
uses: github/codeql-action/init@v3
41+
with:
42+
languages: go
43+
# `security-and-quality` is broader than `security-extended` and
44+
# catches code-quality issues; flip to `security-extended` if the
45+
# noise outweighs the value.
46+
queries: security-and-quality
47+
48+
- name: Autobuild
49+
uses: github/codeql-action/autobuild@v3
50+
51+
- name: Perform CodeQL analysis
52+
uses: github/codeql-action/analyze@v3
53+
with:
54+
category: '/language:go'

.github/workflows/govulncheck.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: govulncheck
2+
3+
# Go's official vulnerability scanner. Reads go.mod + the actual call graph
4+
# of the source and cross-references against vuln.go.dev. More precise than
5+
# Dependabot — only flags CVEs that your code actually reaches.
6+
#
7+
# Runs in ~10 seconds on this repo. Failure here is a real "fix this now"
8+
# signal, not a noisy "your dep has a CVE somewhere" advisory.
9+
10+
on:
11+
push:
12+
branches: [master]
13+
pull_request:
14+
branches: [master]
15+
schedule:
16+
# Catch newly-disclosed CVEs in deps that didn't change. Friday morning
17+
# so a fail lands on a workday.
18+
- cron: '0 13 * * 5'
19+
20+
concurrency:
21+
group: ${{ github.workflow }}-${{ github.ref }}
22+
cancel-in-progress: true
23+
24+
permissions:
25+
contents: read
26+
27+
jobs:
28+
govulncheck:
29+
name: govulncheck
30+
runs-on: ubuntu-latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
- uses: actions/setup-go@v5
34+
with:
35+
go-version: stable
36+
check-latest: true
37+
cache: true
38+
- name: Install govulncheck
39+
run: go install golang.org/x/vuln/cmd/govulncheck@latest
40+
- name: Run govulncheck
41+
run: govulncheck ./...

.github/workflows/trivy.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Trivy
2+
3+
# Scans the Docker image we publish to Docker Hub for OS-level CVEs (alpine
4+
# packages) and Go-binary CVEs. Different surface from govulncheck — that
5+
# one looks at source + go.mod, this one looks at the actual published
6+
# artifact.
7+
#
8+
# We scan both on PR (to catch a fresh CVE in a base image bump before
9+
# merge) and on schedule (to catch a newly-disclosed CVE in an unchanged
10+
# image).
11+
12+
on:
13+
push:
14+
branches: [master]
15+
paths:
16+
- 'Dockerfile'
17+
- 'Makefile'
18+
- '.github/workflows/trivy.yml'
19+
pull_request:
20+
branches: [master]
21+
paths:
22+
- 'Dockerfile'
23+
- 'Makefile'
24+
- '.github/workflows/trivy.yml'
25+
schedule:
26+
- cron: '0 13 * * 5'
27+
28+
concurrency:
29+
group: ${{ github.workflow }}-${{ github.ref }}
30+
cancel-in-progress: true
31+
32+
permissions:
33+
contents: read
34+
security-events: write
35+
36+
jobs:
37+
image-scan:
38+
name: Image scan
39+
runs-on: ubuntu-latest
40+
steps:
41+
- uses: actions/checkout@v4
42+
- uses: actions/setup-go@v5
43+
with:
44+
go-version: stable
45+
check-latest: true
46+
cache: true
47+
48+
- name: Build linux binary (matches the production Dockerfile copy step)
49+
run: make build_linux
50+
51+
- name: Build local Docker image for scanning
52+
run: docker build -t altair-trivy-scan:local -f ./Dockerfile .
53+
54+
- name: Scan image for HIGH and CRITICAL vulnerabilities
55+
uses: aquasecurity/trivy-action@0.28.0
56+
with:
57+
image-ref: altair-trivy-scan:local
58+
format: sarif
59+
output: trivy-results.sarif
60+
severity: HIGH,CRITICAL
61+
# Don't fail the build immediately on every CVE — populate the
62+
# Security tab and let humans triage. Flip ignore-unfixed to
63+
# false and exit-code to 1 once you want hard-fail semantics.
64+
ignore-unfixed: true
65+
exit-code: '0'
66+
67+
- name: Upload Trivy results to GitHub Security tab
68+
uses: github/codeql-action/upload-sarif@v3
69+
if: always()
70+
with:
71+
sarif_file: trivy-results.sarif
72+
category: trivy-image

0 commit comments

Comments
 (0)