Skip to content

Vulnerability Scan & Triage #10

Vulnerability Scan & Triage

Vulnerability Scan & Triage #10

name: Vulnerability Scan & Triage
on:
# schedule:
# # Run nightly at 2am UTC
# - cron: '0 2 * * *'
workflow_dispatch:
inputs:
image_tag:
description: 'Image tag to scan (default: latest)'
required: false
default: 'latest'
dry_run:
description: 'Dry run (analyze but do not create Linear issues)'
required: false
type: boolean
default: false
env:
IMAGE: ghcr.io/sourcebot-dev/sourcebot
permissions:
contents: read
packages: read
id-token: write # Required for OIDC authentication
jobs:
scan:
name: Trivy Scan
runs-on: ubuntu-latest
outputs:
has_vulnerabilities: ${{ steps.check.outputs.has_vulnerabilities }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: "${{ env.IMAGE }}:${{ inputs.image_tag || 'latest' }}"
format: "table"
output: "trivy-results.txt"
trivy-config: trivy.yaml
- name: Check for vulnerabilities
id: check
run: |
if [ -s trivy-results.txt ] && grep -qE "Total: [1-9]" trivy-results.txt; then
echo "has_vulnerabilities=true" >> "$GITHUB_OUTPUT"
else
echo "has_vulnerabilities=false" >> "$GITHUB_OUTPUT"
fi
- name: Upload scan results
if: steps.check.outputs.has_vulnerabilities == 'true'
uses: actions/upload-artifact@v4
with:
name: trivy-results
path: trivy-results.txt
retention-days: 30
triage:
name: Claude Analysis & Linear Triage
needs: scan
if: needs.scan.outputs.has_vulnerabilities == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Download scan results
uses: actions/download-artifact@v4
with:
name: trivy-results
- name: Analyze and create Linear issues
id: claude
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
claude_args: |
--allowedTools Bash,Read,Write,Edit,Glob,Grep,WebSearch,WebFetch
--model claude-sonnet-4-6
--json-schema '{"type":"object","properties":{"report":{"type":"string","description":"Full vulnerability triage report in markdown format"}},"required":["report"]}'
prompt: |
You are a security engineer triaging a Trivy vulnerability scan for the Sourcebot Docker image.
## Your Task
Your task is to read and analyze the Trivy scan results in `trivy-results.txt`. You should group
CVEs into the minimum set of actionable remediation items. Many CVEs can share a single remediation
item. Read files such as `Dockerfile`, `package.json` and `go.mod` to gather information about
dependencies within Sourcebot. Use `yarn why <package> --recursive` to determine why a given
npm package is being included. Report your findings in a concise and readable format for an engineer
to review.
Return your full report as markdown in the `report` field.
- name: Write job summary
env:
STRUCTURED_OUTPUT: ${{ steps.claude.outputs.structured_output }}
run: echo "$STRUCTURED_OUTPUT" | jq -r '.report' >> "$GITHUB_STEP_SUMMARY"