This repository was archived by the owner on Jul 16, 2026. It is now read-only.
Security Nightly #46
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: Security Nightly | |
| on: | |
| schedule: | |
| - cron: "30 3 * * *" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| security-events: write | |
| issues: write | |
| jobs: | |
| dependency-and-image-audit: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Set up Trivy | |
| uses: aquasecurity/setup-trivy@3fb12ec12f41e471780db15c232d5dd185dcb514 # v0.2.5 | |
| - name: Build images | |
| run: | | |
| docker build -f docker/Dockerfile -t fairvisor-runtime-nightly:scan . | |
| docker build -f docker/Dockerfile.cli -t fairvisor-cli-nightly:scan . | |
| - name: Generate SARIF scan reports | |
| run: | | |
| mkdir -p artifacts/security-nightly | |
| trivy image --severity HIGH,CRITICAL --exit-code 0 --format sarif --output artifacts/security-nightly/runtime.sarif fairvisor-runtime-nightly:scan | |
| trivy image --severity HIGH,CRITICAL --exit-code 0 --format sarif --output artifacts/security-nightly/cli.sarif fairvisor-cli-nightly:scan | |
| - name: Enforce nightly HIGH/CRITICAL gate | |
| run: | | |
| trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed fairvisor-runtime-nightly:scan | |
| trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed fairvisor-cli-nightly:scan | |
| - name: Upload SARIF runtime | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 | |
| with: | |
| sarif_file: artifacts/security-nightly/runtime.sarif | |
| category: trivy-nightly-runtime | |
| - name: Upload SARIF cli | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 | |
| with: | |
| sarif_file: artifacts/security-nightly/cli.sarif | |
| category: trivy-nightly-cli | |
| - name: Upload nightly security artifacts | |
| if: always() | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | |
| with: | |
| name: security-nightly-artifacts | |
| path: artifacts/security-nightly | |
| if-no-files-found: ignore | |
| - name: Check lua-resty-maxminddb OPM version | |
| if: always() | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| PINNED=$(grep -oP 'lua-resty-maxminddb=\K[0-9.]+' docker/Dockerfile) | |
| LATEST=$(gh api repos/anjia0532/lua-resty-maxminddb/releases/latest --jq '.tag_name | ltrimstr("v")') | |
| echo "Pinned: $PINNED Latest: $LATEST" | |
| if [ "$PINNED" != "$LATEST" ]; then | |
| TITLE="ci: lua-resty-maxminddb update available ($PINNED to $LATEST)" | |
| EXISTING=$(gh issue list --label dependencies --state open --json title,number \ | |
| --jq ".[] | select(.title == \"$TITLE\") | .number" | head -1) | |
| if [ -z "$EXISTING" ]; then | |
| gh issue create \ | |
| --title "$TITLE" \ | |
| --body "Pinned version in \`docker/Dockerfile\`: \`$PINNED\`. Latest release: \`$LATEST\`. Update the \`opm get\` pin and re-verify the base image digest." \ | |
| --label "dependencies" | |
| else | |
| echo "Issue already open: #$EXISTING — skipping" | |
| fi | |
| fi | |
| - name: Scan for unpinned dependency references | |
| if: always() | |
| id: unpinned_deps | |
| continue-on-error: true | |
| run: | | |
| python3 bin/ci/check_unpinned_dependencies.py \ | |
| --format markdown \ | |
| --output artifacts/security-nightly/unpinned-dependencies.md | |
| - name: Open or update issue for unpinned dependency references | |
| if: always() && steps.unpinned_deps.outcome == 'failure' | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const fs = require("fs"); | |
| const title = "security: unpinned dependency references detected"; | |
| const report = fs.readFileSync("artifacts/security-nightly/unpinned-dependencies.md", "utf8"); | |
| const body = [ | |
| "Nightly guardrail found unpinned dependency references that increase supply-chain risk.", | |
| "", | |
| `Run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, | |
| `Commit: ${context.sha}`, | |
| "", | |
| report, | |
| ].join("\n"); | |
| const { data: issues } = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: "open", | |
| labels: "security,dependencies", | |
| per_page: 100, | |
| }); | |
| const existing = issues.find((issue) => issue.title === title); | |
| if (existing) { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: existing.number, | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title, | |
| body, | |
| labels: ["security", "dependencies", "ci"], | |
| }); | |
| } | |
| - name: Open issue on nightly security failure | |
| if: failure() | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 | |
| with: | |
| script: | | |
| const title = "security: nightly high/critical findings"; | |
| const body = [ | |
| "Nightly security scan found HIGH/CRITICAL issues.", | |
| "", | |
| `Run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, | |
| `Commit: ${context.sha}`, | |
| ].join("\n"); | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title, | |
| body, | |
| labels: ["security", "ci"], | |
| }); |