Vulnerability Scan & Triage #10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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" |