From 1064447553353df1d94bba8abd0df0f45f86c22f Mon Sep 17 00:00:00 2001 From: Thomas Kosiewski Date: Sat, 14 Feb 2026 11:24:42 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A4=96=20ci:=20add=20code=20and=20ima?= =?UTF-8?q?ge=20security=20scanning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add CodeQL code scanning and Trivy filesystem/image scanning across CI and release workflows. Also gate publish-main on security scan jobs and enable GoReleaser image SBOM generation. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: $0.34_ --- .github/workflows/ci.yaml | 74 +++++++++++++++++++++++++++++++++- .github/workflows/codeql.yaml | 38 +++++++++++++++++ .github/workflows/release.yaml | 8 ++++ .goreleaser.yaml | 2 +- 4 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/codeql.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 583748b8..b98304bb 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -113,6 +113,29 @@ jobs: - name: Run govulncheck run: go tool govulncheck ./... + scan-fs: + name: Trivy filesystem scan + needs: changes + if: github.event_name == 'merge_group' || ((needs.changes.outputs.go == 'true' || needs.changes.outputs.workflows == 'true') && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) + runs-on: depot-ubuntu-24.04-8 + timeout-minutes: 20 + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + + - name: Trivy filesystem scan + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + with: + scan-type: fs + scan-ref: . + skip-dirs: vendor + severity: HIGH,CRITICAL + exit-code: '1' + test: needs: changes if: github.event_name == 'merge_group' || (needs.changes.outputs.go == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) @@ -290,6 +313,45 @@ jobs: echo "=== CNPG controller logs ===" kubectl -n cnpg-system logs deploy/cnpg-controller-manager --tail=200 || true + image-scan: + name: Trivy image scan + needs: changes + if: github.event_name == 'merge_group' || (needs.changes.outputs.publish == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) + runs-on: depot-ubuntu-24.04-8 + timeout-minutes: 20 + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version-file: go.mod + cache: true + + - name: Build linux/amd64 binary for image + env: + GOFLAGS: -mod=vendor + CGO_ENABLED: "0" + GOOS: linux + GOARCH: amd64 + run: | + mkdir -p linux/amd64 + go build -o linux/amd64/coder-k8s ./ + + - name: Build local image + run: docker build -f Dockerfile.goreleaser -t coder-k8s:scan . + + - name: Trivy image scan + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + with: + scan-type: image + image-ref: coder-k8s:scan + severity: HIGH,CRITICAL + exit-code: '1' + terraform: name: Terraform (fmt/validate/tflint/trivy) needs: changes @@ -393,7 +455,7 @@ jobs: publish-main: name: Publish GHCR :main - needs: [changes, test, lint, lint-actions, e2e-kind, terraform] + needs: [changes, test, lint, scan-fs, lint-actions, e2e-kind, image-scan, terraform] if: | always() && github.event_name == 'push' && @@ -401,8 +463,10 @@ jobs: needs.changes.outputs.publish == 'true' && (needs.test.result == 'success' || needs.test.result == 'skipped') && (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.scan-fs.result == 'success' || needs.scan-fs.result == 'skipped') && (needs.lint-actions.result == 'success' || needs.lint-actions.result == 'skipped') && (needs.e2e-kind.result == 'success' || needs.e2e-kind.result == 'skipped') && + (needs.image-scan.result == 'success' || needs.image-scan.result == 'skipped') && (needs.terraform.result == 'success' || needs.terraform.result == 'skipped') runs-on: depot-ubuntu-24.04-8 timeout-minutes: 30 @@ -464,3 +528,11 @@ jobs: org.opencontainers.image.vendor=Coder org.opencontainers.image.licenses=Apache-2.0 org.opencontainers.image.authors=Coder + + - name: Trivy image scan (:main) + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + with: + scan-type: image + image-ref: ghcr.io/coder/coder-k8s:main + severity: HIGH,CRITICAL + exit-code: '1' diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml new file mode 100644 index 00000000..16a343b8 --- /dev/null +++ b/.github/workflows/codeql.yaml @@ -0,0 +1,38 @@ +name: CodeQL + +on: + pull_request: + push: + branches: + - main + schedule: + - cron: '0 6 * * 1' + +permissions: + contents: read + security-events: write + actions: read + +jobs: + analyze: + name: Analyze (Go) + runs-on: depot-ubuntu-24.04-8 + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + + - name: Initialize CodeQL + uses: github/codeql-action/init@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3 + with: + languages: go + + - name: Build + env: + GOFLAGS: -mod=vendor + run: go build ./... + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0a344c49..c6f59140 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -43,3 +43,11 @@ jobs: args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Trivy image scan (release) + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + with: + scan-type: image + image-ref: ghcr.io/coder/coder-k8s:${{ github.event.release.tag_name }} + severity: HIGH,CRITICAL + exit-code: '1' diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 1c297aa3..77153c52 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -38,7 +38,7 @@ dockers_v2: - latest platforms: - linux/amd64 - sbom: false + sbom: true labels: org.opencontainers.image.created: "{{ .Date }}" org.opencontainers.image.source: https://github.com/coder/coder-k8s From a6bcbf95701d2cf952e274599677fb90575721b5 Mon Sep 17 00:00:00 2001 From: Thomas Kosiewski Date: Sat, 14 Feb 2026 11:32:44 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=A4=96=20ci:=20address=20codex=20scan?= =?UTF-8?q?=20workflow=20feedback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pin Go setup in CodeQL workflow and compute release image tag without a leading `v` before Trivy scanning. --- _Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: $0.34_ --- .github/workflows/codeql.yaml | 6 ++++++ .github/workflows/release.yaml | 11 ++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 16a343b8..5b1de6ef 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -24,6 +24,12 @@ jobs: with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version-file: go.mod + cache: true + - name: Initialize CodeQL uses: github/codeql-action/init@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3 with: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c6f59140..bd0cb98d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -44,10 +44,19 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Compute release image tag + id: release_image_tag + env: + RELEASE_TAG: ${{ github.event.release.tag_name }} + run: | + IMAGE_TAG="${RELEASE_TAG#v}" + test -n "$IMAGE_TAG" + echo "value=$IMAGE_TAG" >> "$GITHUB_OUTPUT" + - name: Trivy image scan (release) uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 with: scan-type: image - image-ref: ghcr.io/coder/coder-k8s:${{ github.event.release.tag_name }} + image-ref: ghcr.io/coder/coder-k8s:${{ steps.release_image_tag.outputs.value }} severity: HIGH,CRITICAL exit-code: '1'