Skip to content

Commit 3058ca6

Browse files
chore(debs): add sec scans with trivy
* fix(deps): update golang.org/x/* dependencies to fix CVEs Updates golang.org/x/* packages to their latest versions: - golang.org/x/net v0.38.0 → v0.50.0 (fixes 2 MEDIUM CVEs) - golang.org/x/oauth2 v0.27.0 → v0.35.0 - golang.org/x/sys v0.31.0 → v0.41.0 - golang.org/x/text v0.23.0 → v0.34.0 Also updated related packages (sync, term, tools) to maintain compatibility. This addresses 2 MEDIUM severity CVEs identified in Docker Hub security scan. Testing: - All unit tests pass - Build compiles successfully * fix(go): upgrade to Go 1.25 to fix stdlib CVEs Updates Go version from 1.24.0 to 1.25 to address critical vulnerabilities: - Fixes 2 CRITICAL severity CVEs in golang stdlib - Fixes 7 HIGH severity CVEs in golang stdlib - Fixes 12 MEDIUM severity CVEs in golang stdlib Changes: - go.mod: Update go directive to 1.25 - Dockerfile: Update base image to golang:1.25 - CI workflows already use go-version-file, so they'll pick up the new version automatically This addresses the most severe vulnerabilities identified in Docker Hub security scan. Testing: - All unit tests pass with Go 1.25 - Build compiles successfully * feat(security): add Trivy scanning and enhanced Dependabot Implements comprehensive security scanning infrastructure: Security Scanning: - Add Trivy security scan job to CI pipeline (fails on HIGH/CRITICAL) - Create daily scheduled scan workflow for published images - Upload scan results to GitHub Security tab (SARIF format) - Auto-create issues when vulnerabilities are detected Trivy Configuration: - Add .trivy.yaml with severity levels (CRITICAL, HIGH) - Create .trivyignore for managing false positives - Add .trivycache/ to .gitignore Dependabot Enhancements: - Add gomod package ecosystem (weekly scans) - Add docker package ecosystem (base image updates) - Group related updates (K8s, OpenTelemetry, golang.org/x/*) - Add consistent labels to all ecosystems This prevents future CVE accumulation and provides early warning when new vulnerabilities are disclosed in our dependencies or published Docker images. * docs(security): add documentation and build hardening Documentation Updates: - Update SECURITY.md with CVE remediation process and timelines - Document vulnerability scanning workflow (PR scans + daily scans) - Add instructions for updating base image digests - Explain false positive management with .trivyignore - Add security badge to README.md linking to GitHub Security tab Build Hardening: - Pin distroless base image by SHA256 digest for reproducibility - Add OCI image labels (source, description, license, vendor, docs) - Add SBOM generation to release workflow (SPDX + CycloneDX) - Attach SBOMs to GitHub releases for supply chain transparency These changes complete the CVE remediation infrastructure by documenting processes and hardening the container build for reproducibility and supply chain security. * fix(docker): remove SHA256 digest pinning from base image Remove SHA256 digest from distroless base image to simplify maintenance while retaining nonroot tag for security. The digest pinning was causing maintenance overhead without significant security benefit given the existing tag-based approach and automated dependency updates. * fix(ci): update golangci-lint to support Go 1.25 Use latest version of golangci-lint instead of v2.1.0 which was built with Go 1.24 and doesn't support Go 1.25. This fixes the CI error: 'the Go language version (go1.24) used to build golangci-lint is lower than the targeted Go version (1.25)' * fix(codacy): explicitly disable markdown file analysis Add comprehensive markdown exclusion patterns and disable all markdown-related analysis engines (markdownlint, remark-lint, prose) to prevent Codacy from analyzing .md files. * fix(codacy): remove redundant prose engine configuration The prose engine is not a standard Codacy engine and was causing configuration warnings. Markdown analysis is already disabled via markdownlint and remark-lint engines.
1 parent 3c88a5e commit 3058ca6

File tree

13 files changed

+449
-28
lines changed

13 files changed

+449
-28
lines changed

.codacy.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1+
---
12
exclude_paths:
23
- "**/zz_generated.deepcopy.go"
34
- "test/utils/**"
45
- "**/*.md"
6+
- "**.md"
7+
- "*.md"
8+
- "docs/**"
9+
- "README.md"
10+
- "SECURITY.md"
11+
- "CONTRIBUTING.md"
12+
- "LICENSE"
13+
14+
engines:
15+
markdownlint:
16+
enabled: false
17+
remark-lint:
18+
enabled: false

.github/dependabot.yml

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,47 @@
55

66
version: 2
77
updates:
8-
- package-ecosystem: "gradle" # See documentation for possible values
9-
directory: "/" # Location of package manifests
8+
# Go module dependencies
9+
- package-ecosystem: "gomod"
10+
directory: "/"
11+
schedule:
12+
interval: "weekly"
13+
groups:
14+
kubernetes:
15+
patterns:
16+
- "k8s.io/*"
17+
- "sigs.k8s.io/*"
18+
opentelemetry:
19+
patterns:
20+
- "go.opentelemetry.io/*"
21+
golang-x:
22+
patterns:
23+
- "golang.org/x/*"
24+
labels:
25+
- "dependencies"
26+
- "go"
27+
28+
# Docker base images
29+
- package-ecosystem: "docker"
30+
directory: "/"
31+
schedule:
32+
interval: "weekly"
33+
labels:
34+
- "dependencies"
35+
- "docker"
36+
37+
- package-ecosystem: "gradle"
38+
directory: "/"
1039
schedule:
1140
interval: "weekly"
41+
labels:
42+
- "dependencies"
43+
- "gradle"
1244

1345
- package-ecosystem: "github-actions"
1446
directory: "/"
1547
schedule:
1648
interval: "weekly"
49+
labels:
50+
- "dependencies"
51+
- "github-actions"

.github/workflows/ci.yaml

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ on:
1111
types: [opened, synchronize, reopened, ready_for_review]
1212

1313
# Sets default read-only permissions for the workflow.
14-
permissions: read-all
14+
permissions:
15+
contents: read
16+
security-events: write # Required for uploading SARIF to GitHub Security tab
1517

1618
jobs:
1719
# ============================================
@@ -39,7 +41,7 @@ jobs:
3941
- name: 🔍 Run linter
4042
uses: golangci/golangci-lint-action@v8
4143
with:
42-
version: v2.1.0
44+
version: latest # Use latest to support Go 1.25
4345

4446
- name: 🛠️ Build
4547
run: make build
@@ -195,3 +197,57 @@ jobs:
195197
path: |
196198
site/
197199
retention-days: 7
200+
201+
# ============================================
202+
# Security Scanning with Trivy
203+
# ============================================
204+
security-scan:
205+
name: 🔒 Security scan
206+
runs-on: ubuntu-latest
207+
timeout-minutes: 15
208+
steps:
209+
- name: 📂 Checkout
210+
uses: actions/checkout@v4
211+
with:
212+
ref: ${{ github.event.pull_request.head.sha }}
213+
repository: ${{ github.event.pull_request.head.repo.full_name }}
214+
215+
- name: 🔧 Setup Go
216+
uses: actions/setup-go@v5
217+
with:
218+
go-version-file: go.mod
219+
220+
- name: 🛠️ Install ko
221+
uses: ko-build/setup-ko@v0.7
222+
223+
- name: 🐳 Build operator image with ko
224+
env:
225+
KO_DOCKER_REPO: lotest/locust-k8s-operator
226+
run: |
227+
CHART_VERSION=$(grep '^appVersion:' charts/locust-k8s-operator/Chart.yaml | awk '{print $2}' | tr -d '"')
228+
ko build ./cmd --local --bare --tags=${CHART_VERSION}
229+
echo "IMAGE_TAG=${CHART_VERSION}" >> $GITHUB_ENV
230+
231+
- name: 🔍 Run Trivy security scan
232+
uses: aquasecurity/trivy-action@0.29.0
233+
with:
234+
image-ref: lotest/locust-k8s-operator:${{ env.IMAGE_TAG }}
235+
format: sarif
236+
output: trivy-results.sarif
237+
severity: CRITICAL,HIGH
238+
exit-code: 1 # Fail the build if vulnerabilities are found
239+
240+
- name: 📊 Upload Trivy results to GitHub Security tab
241+
if: always()
242+
uses: github/codeql-action/upload-sarif@v3
243+
with:
244+
sarif_file: trivy-results.sarif
245+
category: trivy-container-scan
246+
247+
- name: 📦 Upload Trivy scan artifacts on failure
248+
if: failure()
249+
uses: actions/upload-artifact@v4
250+
with:
251+
name: trivy-scan-results
252+
path: trivy-results.sarif
253+
retention-days: 7

.github/workflows/release.yaml

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
runs-on: ubuntu-latest
1717
timeout-minutes: 30
1818
permissions:
19-
contents: read
19+
contents: write # Required for uploading release assets
2020
env:
2121
DOCKER_IMAGE: lotest/locust-k8s-operator
2222
steps:
@@ -46,6 +46,37 @@ jobs:
4646
--bare \
4747
--tags=${{ github.ref_name }},latest
4848

49+
- name: 🔍 Install Trivy
50+
run: |
51+
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
52+
echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
53+
sudo apt-get update
54+
sudo apt-get install trivy
55+
56+
- name: 📋 Generate SBOM (SPDX format)
57+
run: |
58+
trivy image \
59+
--format spdx-json \
60+
--output sbom-spdx.json \
61+
${{ env.DOCKER_IMAGE }}:${{ github.ref_name }}
62+
63+
- name: 📋 Generate SBOM (CycloneDX format)
64+
run: |
65+
trivy image \
66+
--format cyclonedx \
67+
--output sbom-cyclonedx.json \
68+
${{ env.DOCKER_IMAGE }}:${{ github.ref_name }}
69+
70+
- name: 📦 Upload SBOMs to release
71+
uses: softprops/action-gh-release@v2
72+
with:
73+
files: |
74+
sbom-spdx.json
75+
sbom-cyclonedx.json
76+
fail_on_unmatched_files: false
77+
env:
78+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
79+
4980
helm-chart-release:
5081
name: 🌊 Publish Helm chart
5182
runs-on: ubuntu-latest
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Daily security scan of published Docker images
2+
name: 🔒 Daily Security Scan
3+
4+
on:
5+
schedule:
6+
# Run daily at 6 AM UTC
7+
- cron: '0 6 * * *'
8+
workflow_dispatch: # Allow manual trigger
9+
10+
permissions:
11+
contents: read
12+
security-events: write
13+
issues: write # Required for creating issues on vulnerabilities
14+
15+
jobs:
16+
scan-published-image:
17+
name: 🔍 Scan published image
18+
runs-on: ubuntu-latest
19+
timeout-minutes: 15
20+
steps:
21+
- name: 📂 Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: 🔍 Run Trivy scan on latest image
25+
uses: aquasecurity/trivy-action@0.29.0
26+
id: trivy-scan
27+
with:
28+
image-ref: lotest/locust-k8s-operator:latest
29+
format: sarif
30+
output: trivy-results.sarif
31+
severity: CRITICAL,HIGH
32+
exit-code: 0 # Don't fail, we'll create an issue instead
33+
34+
- name: 📊 Upload Trivy results to GitHub Security tab
35+
if: always()
36+
uses: github/codeql-action/upload-sarif@v3
37+
with:
38+
sarif_file: trivy-results.sarif
39+
category: trivy-daily-scan
40+
41+
- name: 🔍 Check for vulnerabilities
42+
id: check-vulns
43+
run: |
44+
# Check if SARIF file contains vulnerabilities
45+
if grep -q '"level": "error"' trivy-results.sarif || grep -q '"level": "warning"' trivy-results.sarif; then
46+
echo "vulnerabilities_found=true" >> $GITHUB_OUTPUT
47+
else
48+
echo "vulnerabilities_found=false" >> $GITHUB_OUTPUT
49+
fi
50+
51+
- name: 🚨 Create issue for vulnerabilities
52+
if: steps.check-vulns.outputs.vulnerabilities_found == 'true'
53+
uses: actions/github-script@v7
54+
with:
55+
script: |
56+
const fs = require('fs');
57+
const sarif = JSON.parse(fs.readFileSync('trivy-results.sarif', 'utf8'));
58+
59+
let vulnerabilities = [];
60+
for (const run of sarif.runs) {
61+
for (const result of run.results || []) {
62+
const severity = result.level === 'error' ? 'CRITICAL/HIGH' : 'MEDIUM';
63+
const ruleId = result.ruleId || 'Unknown';
64+
const message = result.message?.text || 'No description';
65+
vulnerabilities.push(`- **${ruleId}** (${severity}): ${message}`);
66+
}
67+
}
68+
69+
if (vulnerabilities.length === 0) {
70+
console.log('No vulnerabilities found in SARIF');
71+
return;
72+
}
73+
74+
const issueTitle = `🚨 Security vulnerabilities found in latest Docker image`;
75+
const issueBody = `## Security Scan Alert
76+
77+
Daily security scan detected vulnerabilities in \`lotest/locust-k8s-operator:latest\`.
78+
79+
### Vulnerabilities Found:
80+
${vulnerabilities.slice(0, 20).join('\n')}
81+
${vulnerabilities.length > 20 ? `\n\n... and ${vulnerabilities.length - 20} more` : ''}
82+
83+
### Next Steps:
84+
1. Review the full scan results in the [Security tab](${context.payload.repository.html_url}/security/code-scanning)
85+
2. Update dependencies or Go version as needed
86+
3. Rebuild and push a new image
87+
88+
**Scan Date:** ${new Date().toISOString().split('T')[0]}
89+
**Image:** lotest/locust-k8s-operator:latest
90+
`;
91+
92+
// Check if an open issue already exists
93+
const issues = await github.rest.issues.listForRepo({
94+
owner: context.repo.owner,
95+
repo: context.repo.repo,
96+
state: 'open',
97+
labels: 'security,automated'
98+
});
99+
100+
const existingIssue = issues.data.find(issue =>
101+
issue.title.includes('Security vulnerabilities found')
102+
);
103+
104+
if (existingIssue) {
105+
// Update existing issue
106+
await github.rest.issues.createComment({
107+
owner: context.repo.owner,
108+
repo: context.repo.repo,
109+
issue_number: existingIssue.number,
110+
body: `## New Scan Results\n\n${issueBody}`
111+
});
112+
console.log(`Updated existing issue #${existingIssue.number}`);
113+
} else {
114+
// Create new issue
115+
await github.rest.issues.create({
116+
owner: context.repo.owner,
117+
repo: context.repo.repo,
118+
title: issueTitle,
119+
body: issueBody,
120+
labels: ['security', 'automated']
121+
});
122+
console.log('Created new security issue');
123+
}
124+
125+
- name: 📦 Upload scan results
126+
if: always()
127+
uses: actions/upload-artifact@v4
128+
with:
129+
name: trivy-daily-scan-${{ github.run_number }}
130+
path: trivy-results.sarif
131+
retention-days: 30

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ Thumbs.db
4141
.docs-venv
4242
.cache
4343

44+
# Trivy security scanner
45+
.trivycache/
46+
4447
# Agentic flows
4548
specs/
4649
.windsurf/

.trivy.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Trivy security scanner configuration
2+
# Documentation: https://aquasecurity.github.io/trivy/latest/docs/configuration/
3+
4+
# Severity levels to report
5+
severity:
6+
- CRITICAL
7+
- HIGH
8+
9+
# Vulnerability types to scan
10+
vuln-type:
11+
- os
12+
- library
13+
14+
# Output format (can be overridden in CLI)
15+
format: table
16+
17+
# Exit with error if vulnerabilities are found
18+
exit-code: 1
19+
20+
# Timeout for scanning
21+
timeout: 5m0s
22+
23+
# Skip files and directories
24+
skip-dirs:
25+
- .git
26+
- .github
27+
- docs
28+
- test
29+
- bin
30+
31+
# Ignore unfixed vulnerabilities (set to false to see all)
32+
ignore-unfixed: false
33+
34+
# Cache directory
35+
cache-dir: .trivycache/

.trivyignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Trivy ignore file for false positives
2+
# Documentation: https://aquasecurity.github.io/trivy/latest/docs/configuration/filtering/#by-finding-ids
3+
4+
# To ignore a specific CVE, add it below with a justification comment:
5+
# Example:
6+
# CVE-2024-1234 # False positive: not used in our codebase, expires 2025-06-01
7+
8+
# Currently no vulnerabilities are ignored

0 commit comments

Comments
 (0)