Skip to content

fix(security): bump dependencies to clear OSV-Scanner advisories #40

fix(security): bump dependencies to clear OSV-Scanner advisories

fix(security): bump dependencies to clear OSV-Scanner advisories #40

name: Security Audit
# Scans the resolved dependency lockfile (uv.lock) for known vulnerabilities
# using OSV-Scanner. Because it reads uv.lock statically, it audits every pinned
# version across all supported Python versions (3.10-3.13) and platforms.
# Results are uploaded to GitHub code scanning (Security tab) as SARIF, so a
# newly-disclosed CVE in a pinned dependency surfaces as a failing check and a
# code-scanning alert rather than a passive Dependabot alert.
#
# Suppressions (each with a rationale, and an ignoreUntil expiry where a fix may
# yet appear) live in osv-scanner.toml at the repo root.
#
# On pull requests the scan runs only when dependencies or this workflow change,
# and is advisory (results still post to code scanning); pushes to main (same
# path filter) refresh the default-branch code-scanning state, and manual
# dispatches and release calls are hard gates. Detection of newly-disclosed CVEs
# against already-pinned dependencies (with no repo change) is left to Dependabot
# alerts and security updates, so no scheduled scan is needed here.
on:
pull_request:
types: [opened, synchronize]
paths:
- "uv.lock"
- "pyproject.toml"
- "osv-scanner.toml"
- ".github/workflows/security-audit.yml"
push:
branches: [main]
paths:
- "uv.lock"
- "pyproject.toml"
- "osv-scanner.toml"
- ".github/workflows/security-audit.yml"
workflow_dispatch:
workflow_call:
permissions: {}
concurrency:
group: "security-audit-${{ github.ref }}-${{ github.event_name }}"
cancel-in-progress: true
jobs:
osv-scan:
name: OSV-Scanner (uv.lock)
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
security-events: write # upload SARIF to code scanning
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Run OSV-Scanner
id: osv
continue-on-error: true # gate is enforced explicitly below, after SARIF upload
uses: google/osv-scanner-action/osv-scanner-action@9a498708959aeaef5ef730655706c5a1df1edbc2 # v2.3.8
with:
scan-args: |-
--config=osv-scanner.toml
--format=sarif
--output=results.sarif
--lockfile=uv.lock
- name: Upload results to code scanning
# Skip cleanly if the scanner errored before writing the SARIF, rather
# than erroring and being swallowed by continue-on-error.
if: always() && hashFiles('results.sarif') != ''
continue-on-error: true # never let SARIF upload (e.g. missing perms) break the gate
uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
with:
sarif_file: results.sarif
category: osv-scanner
- name: Enforce gate
# Pull requests are advisory only (results still post to code scanning);
# every other trigger is a hard gate. Fail closed: block unless the scan
# completed successfully, so a failed, errored, or skipped scan never
# passes the gate. !cancelled() (rather than always()) avoids marking a
# concurrency-superseded run as failed; a real timeout still blocks
# downstream via the job's needs dependency.
if: ${{ !cancelled() && github.event_name != 'pull_request' && steps.osv.outcome != 'success' }}
run: |
echo "::error::OSV-Scanner did not complete cleanly (vulnerabilities found or scan failed) — see the SARIF results in the Security tab."
exit 1