From a4f8f91e50cabed4e5b6901bcb85a08e8446bb66 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Tue, 15 Sep 2026 04:50:35 -0700 Subject: [PATCH] ci: run the OSV lockfile scan weekly against main, not on every PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .github/workflows/ci.yaml | 15 ++--- .github/workflows/osv-scanner.yml | 102 ++---------------------------- 2 files changed, 8 insertions(+), 109 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1d4c3638cd..973f4b0917 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -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 diff --git a/.github/workflows/osv-scanner.yml b/.github/workflows/osv-scanner.yml index 2e61fcc92c..c7634bb833 100644 --- a/.github/workflows/osv-scanner.yml +++ b/.github/workflows/osv-scanner.yml @@ -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