Skip to content

build(deps): Bump google/osv-scanner-action/osv-scanner-action from 9fd1bcce27f67e3bd819a0a7620e332803dc43bc to f4cfcc01edc9c8b756a9b873b7a623ca674da51e #800

build(deps): Bump google/osv-scanner-action/osv-scanner-action from 9fd1bcce27f67e3bd819a0a7620e332803dc43bc to f4cfcc01edc9c8b756a9b873b7a623ca674da51e

build(deps): Bump google/osv-scanner-action/osv-scanner-action from 9fd1bcce27f67e3bd819a0a7620e332803dc43bc to f4cfcc01edc9c8b756a9b873b7a623ca674da51e #800

Workflow file for this run

# Supply-chain security gate.
#
# Scans the resolved dependency tree (bun.lock) against the OSV.dev database —
# which aggregates GitHub/npm security advisories AND the OpenSSF
# malicious-packages feed — and FAILS on any known-vulnerable or known-malicious
# package (block-on-any-finding policy). OSV-Scanner exits non-zero when it finds
# anything, which fails this job.
#
# Runs on every PR (incl. Dependabot bumps), on pushes to main, and daily to
# catch advisories disclosed after a dependency was already merged — a PR is
# the only thing that surfaced a scheduled failure before this, so a scan that
# broke on `main` between PRs went unnoticed until the next one happened to
# touch the lockfile.
#
# A daily scheduled failure also posts to Slack (see the notify step below,
# gated on github.event_name == 'schedule') — PR and push runs don't, since
# those failures are already visible to whoever opened or merged the PR
# without needing a second channel. Posting is itself optional: it silently
# no-ops when the SLACK_WEBHOOK_URL repository secret isn't set.
#
# Triage / allow-listing unfixable advisories: see SECURITY.md and osv-scanner.toml
# (auto-loaded from the repo root by OSV-Scanner).
#
# Third-party actions are pinned to a commit SHA (we're a supply-chain tool —
# practice what we preach).
name: Supply Chain
on:
pull_request:
branches: [main]
push:
branches: [main]
schedule:
- cron: "17 4 * * *" # daily, 04:17 UTC
workflow_dispatch:
# Least privilege: the scan only needs to read the checked-out source.
# contents:read is also available to Dependabot PRs (read-only token), so the
# gate enforces on dependency-bump PRs too.
permissions:
contents: read
jobs:
osv-scanner:
name: OSV-Scanner
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# No git ops after checkout; don't leave the token in .git/config.
persist-credentials: false
# Both lockfiles, in one scan. `Cargo.lock`'s 238 packages were covered by
# nothing at all — not this job, which was only ever given `bun.lock`, and
# not Dependabot, which had no `cargo` ecosystem — for a TLS stack that
# compiles into a root-installed system service.
- name: Scan bun.lock and Cargo.lock for known-vulnerable / malicious dependencies
id: scan
uses: google/osv-scanner-action/osv-scanner-action@f4cfcc01edc9c8b756a9b873b7a623ca674da51e # v2.3.8
with:
scan-args: |-
--lockfile=bun.lock
--lockfile=Cargo.lock
# Only the schedule run notifies — nothing on main touched the lockfile,
# so nobody is watching it the way a PR author watches their own checks
# or a push failure shows up against the commit they just merged. Same
# webhook + `node -e … | curl` idiom integration-suite/run.sh uses.
# `failure()` is required, not decorative: a bare `if:` expression is
# implicitly ANDed with success(), so without it this step would be
# skipped every time — the one time it's meant to run is exactly when
# the job already failed.
- name: Notify Slack on failure
if: failure() && steps.scan.outcome == 'failure' && github.event_name == 'schedule'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
if [ -z "$SLACK_WEBHOOK_URL" ]; then
echo "(no SLACK_WEBHOOK_URL set — not posted)" >&2
exit 0
fi
run_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
text="🔴 *Supply Chain scan failed* on \`${GITHUB_REF_NAME}\` (${GITHUB_EVENT_NAME}) — known-vulnerable or known-malicious dependency detected. <${run_url}|View run>"
payload="$(node -e 'const t=require("fs").readFileSync(0,"utf8");process.stdout.write(JSON.stringify({text:t}))' <<<"$text")"
for attempt in 1 2 3; do
code="$(curl -sS --connect-timeout 10 --max-time 30 \
-o /dev/null -w '%{http_code}' -X POST -H 'Content-type: application/json' \
--data "$payload" "$SLACK_WEBHOOK_URL" 2>/dev/null || echo 000)"
if [ "$code" = 200 ]; then echo "✓ posted to Slack webhook"; exit 0; fi
echo "⚠️ Slack webhook POST attempt $attempt returned HTTP $code" >&2
[ "$attempt" -lt 3 ] && sleep 5
done
echo "✗ Slack webhook POST failed after 3 attempts" >&2
exit 1