ci: run the OSV lockfile scan weekly against main, not on every PR

The scan is detection-only and its findings are the repo-wide baseline of
CVEs in pinned dependencies — identical for every PR, unrelated to any
PR's diff. Reporting that baseline in each PR's review comment read as
"this PR has 76 vulnerabilities" to contributors, and the SARIF upload
tripped GitHub's per-installation API rate limit during merge trains.

The scheduled weekly run (plus workflow_dispatch) keeps feeding the
Security tab; the per-PR workflow_call, the review_status wrapper job,
and the orchestrator's now-unneeded SARIF permissions are removed.
This commit is contained in:
teknium1
2026-09-15 04:50:35 -07:00
committed by Teknium
parent f13a87e610
commit a4f8f91e50
2 changed files with 8 additions and 109 deletions

View File

@@ -22,8 +22,6 @@ on:
permissions:
contents: read
pull-requests: write # needed by lint (PR comment) + supply-chain review_status
actions: read # needed by osv-scanner (SARIF upload)
security-events: write # needed by osv-scanner (SARIF upload)
concurrency:
group: ci-${{ github.ref }}
@@ -215,10 +213,6 @@ jobs:
mcp_catalog: ${{ needs.detect.outputs.mcp_catalog == 'true' }}
supply_chain: ${{ needs.supply-chain.outputs.critical_findings == 'true' }}
osv-scanner:
name: OSV scan
uses: ./.github/workflows/osv-scanner.yml
# ─────────────────────────────────────────────────────────────────────
# Gate: runs after everything. ``if: always()`` ensures it reports a
# status even when some deps were skipped. Only actual ``failure``
@@ -250,11 +244,10 @@ jobs:
- profile-artifact-check
- supply-chain
- review-labels
# osv-scanner is deliberately NOT a dependency: osv-scanner.yml is
# detection-only (fail-on-vuln: false, findings go to the Security tab)
# and its SARIF upload trips GitHub's per-installation API rate limit
# during merge trains, which turned an advisory scan into a merge
# blocker for whole batches of unrelated PRs.
# OSV runs weekly against main (osv-scanner.yml schedule), not per PR:
# every PR was reporting the same repo-wide baseline of pinned-dep CVEs
# in its review comment, and the SARIF upload tripped GitHub's
# per-installation API rate limit during merge trains.
# The image build runs in its own workflow (docker.yml) and reports
# its own check. It was never required here, because it is too slow
# to block a merge. A separate run also stops it from holding this

View File

@@ -1,8 +1,10 @@
name: OSV-Scanner
# Scans lockfiles (uv.lock, package-lock.json) against the OSV vulnerability
# database. Runs on every PR/push (via the ci.yml orchestrator's workflow_call)
# and on a weekly schedule against main.
# database. Runs on a weekly schedule against main (and on manual dispatch);
# it is deliberately NOT part of per-PR CI — the findings are the repo-wide
# baseline of pinned-dep CVEs, identical for every PR, and belong in the
# Security tab, not in each PR's review comment.
#
# This is detection-only — OSV-Scanner does NOT open PRs or modify pins.
# It reports known CVEs in currently-pinned dependency versions so we can
@@ -18,13 +20,8 @@ name: OSV-Scanner
# Findings land in the repo's Security tab (Code Scanning > OSV-Scanner).
# fail-on-vuln is disabled so the job does not block merges on pre-existing
# vulnerabilities in pinned deps that we may need to patch deliberately.
#
# The reusable workflow can't emit custom outputs, so a wrapper job
# downloads the SARIF result and summarizes the vulnerability count into
# a review_status for the unified PR comment.
on:
workflow_call:
schedule:
# Weekly scan against main — catches CVEs published after merge for
# deps that haven't changed since.
@@ -50,97 +47,6 @@ jobs:
--lockfile=website/package-lock.json
--lockfile=plugins/platforms/photon/sidecar/package-lock.json
--lockfile=scripts/whatsapp-bridge/package-lock.json
# The upstream reusable workflow uploads this exact file under its
# fixed artifact name, which the wrapper downloads below.
results-file-name: osv-results.sarif
fail-on-vuln: false
emit-status:
name: Emit review status
runs-on: ubuntu-latest
# Downloads one small SARIF artifact and runs two inline python snippets —
# minutes of work. Bound it so a wedged artifact download can't hold a
# runner for GitHub's 6-hour default (the only unbounded job left in
# .github/workflows; every other workflow already sets timeout-minutes).
timeout-minutes: 10
needs: scan
if: always()
outputs:
review_status: ${{ steps.emit.outputs.review_status }}
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Download SARIF result
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: OSV Scanner SARIF file
path: /tmp/osv-results
continue-on-error: true
- name: Emit review_status
id: emit
run: |
set -euo pipefail
STATUS="[]"
if [ -f /tmp/osv-results/osv-results.sarif ]; then
# Count vulnerabilities from the SARIF file
VULN_COUNT=$(python3 -c "
import json, sys
try:
with open('/tmp/osv-results/osv-results.sarif') as f:
data = json.load(f)
count = 0
vulns = []
for run in data.get('runs', []):
for result in run.get('results', []):
count += 1
rule_id = result.get('ruleId', 'unknown')
message = result.get('message', {}).get('text', '')
loc = result.get('locations', [{}])[0].get('physicalLocation', {}).get('artifactLocation', {}).get('uri', '')
vulns.append(f'- {rule_id} in {loc}: {message}')
print(count)
if vulns:
print('\n'.join(vulns[:20]), file=sys.stderr)
except Exception:
print(0)
")
VULN_DETAIL=""
if [ "$VULN_COUNT" -gt 0 ] 2>/dev/null; then
VULN_PLURAL=$([ "$VULN_COUNT" -eq 1 ] && echo "y" || echo "ies")
VULN_DETAIL=$(python3 -c "
import json, sys
try:
with open('/tmp/osv-results/osv-results.sarif') as f:
data = json.load(f)
vulns = []
for run in data.get('runs', []):
for result in run.get('results', []):
rule_id = result.get('ruleId', 'unknown')
loc = result.get('locations', [{}])[0].get('physicalLocation', {}).get('artifactLocation', {}).get('uri', '')
vulns.append(f'- {rule_id} in {loc}')
print(json.dumps('\n'.join(vulns[:20])))
except Exception:
print(json.dumps(''))
")
STATUS="[{\"source\":\"osv scan\",\"results\":[{\"kind\":\"warning\",\"title\":\"OSV vulnerability scan\",\"summary\":\"${VULN_COUNT} known vulnerabilit${VULN_PLURAL} found in pinned dependencies.\",\"detail\":${VULN_DETAIL},\"how_to_fix\":\"Review the findings in the [Security tab](../../security/code-scanning). Update the affected dependencies if a patched version is available.\"}]}]"
else
STATUS="[]"
fi
fi
echo "review_status=${STATUS}" >> "$GITHUB_OUTPUT"
echo "review_status=${STATUS}" > review-status.json
- name: Upload review status artifact
if: always() && steps.emit.outcome != 'skipped'
continue-on-error: true
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: review-status-osv-scanner
path: review-status.json
retention-days: 1
overwrite: true
if-no-files-found: ignore