Skip to content
This repository was archived by the owner on Jul 16, 2026. It is now read-only.

Security Nightly

Security Nightly #46

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"],
});