Repository navigation
ci(validate-deps): judge a pull request's OSV findings against the merge base; main keeps the absolute daily scan; job timeout 15 min - #22138
Merged
objectstack-fleet[bot] merged 7 commits intoOct 8, 2026
Conversation
…rge base, keep main's absolute daily scan, add a job timeout On pull_request the OSV step now scans the pull request's lockfile and the merge base's (each under its own osv-scanner.toml) and fails only on an advisory the merge base does not match; inherited advisories become notices naming the advisory and its open finding card. A pull request that changes neither pnpm-lock.yaml nor osv-scanner.toml short-circuits to "lockfile unchanged — inherits main's verdict". schedule and workflow_dispatch keep the absolute scan unchanged. The job gains timeout-minutes: 15. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
…ed open-issue listing, not the search API The search index lags and this session cannot reach it to verify the query; one listing of the open issues serves every id, finds a card filed minutes ago, and skips seat board posts that quote advisories in passing. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
…guard check:entry-guard: a scripts/ file that exports bindings must not run on import. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
…984h) so the pull_request OSV verdict has a real advisory to introduce Reverted by the next commit; the PR squashes. Its run is the pin's "a lockfile that introduces a new advisory fails" half. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
… manifest are main's again Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
….8 (no advisory) so the lockfile changes without introducing one main's lockfile carries live advisories today, so this run is the pin's "inherited passes with a notice" half on a real merge base. Reverted by the next commit; the PR squashes. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
… manifest are main's again Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw
This was referenced Oct 8, 2026
This was referenced Oct 8, 2026
os-bill
pushed a commit
that referenced
this pull request
Oct 8, 2026
Brings in PR #22138, so this PR's OSV scan judges only what it adds (main's next@16.3.6 advisories, anchor #22148, are the base's). No file is changed on both sides. Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Oct 8, 2026
os-bill
pushed a commit
that referenced
this pull request
Oct 8, 2026
Brings in PR #22138, so this PR's OSV scan judges only what it adds (main's next@16.3.6 advisories, anchor #22148, are the base's). security-plugin.ts and the runtime harness changed on both sides and merged cleanly; the PR's added and removed lines against the new main are identical to the reviewed head 90bb654. Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #22082
Clause-②: no
What this does
Implements ruling A as recorded on the card (comment 6049727506). On
pull_request, the OSV verdict ofvalidate-deps.ymlis now base-relative. Onscheduleandworkflow_dispatch,mainkeeps the absolute verdict from the same step as before. That step's only change isif: github.event_name != 'pull_request'(its version comment is also corrected, see below). The job gainstimeout-minutes: 15, sized from the measured p50 of 1.3 min and max of 1.9 min.pnpm-lock.yamlnorosv-scanner.tomldiffers, the step prints the notice "lockfile unchanged — inherits main's verdict" and runs no scan. The ledger counts as part of the input because a PR that deletes an exemption changes the verdict without touching the lockfile (replay R3 below).osv-scanner.toml, so the merge base's verdict is whatmain's scan gives and the PR's verdict is what the old absolute scan gave.scripts/osv-base-relative.mjsthen sorts the advisories:noticeannotation that names it, the package versions each side matched, and the open finding card that names it, when one exists. It does not fail the step.errorannotation and fails the step, as before.actions/checkoutputs the PR's test merge (refs/pull/N/merge) at depth 1. Its first parent is the base-branch commit that GitHub merged the PR into, which makes it the merge base of the scanned tree. The step reads that parent from the commit object and fetches it with one depth-1git fetch(neverfetch-depth: 0). If HEAD is not a two-parent merge, the step fails with an error annotation.This adds no new gate, changes nothing that
main's scan judges, and adds no exemption.osv-scanner.toml,scripts/check-osv-exemptions.mjsand the other gate scripts are untouched, and they still run first and unchanged.Why a helper script, and why not upstream's
osv-reporter-actionThe upstream reporter was read at
google/osv-scannerv2.5.0 (cmd/osv-reporter/main.go,internal/ci/vulnerability_result_diff.go). Three things rule it out:continue-on-error: true, so a scan error on the PR side passes the gate.source.path, so the base lockfile would have to be swapped into the workspace and restored mid-job.The helper is one definition of introduced versus inherited, with the scan-error guard built in. Its
--self-test(23 cases, floor pinned) runs as the first line of the stage step, socheck:self-test-wiredsees it. The helper is in thepaths:filter, so a PR that edits it runs this workflow.Measured mechanism (osv-scanner 2.5.0, the binary in the pinned action's image)
f4cfcc01edc9c8b756a9b873b7a623ca674da51eis an untagged upstream commit between the v2.5.0 and v2.5.1 tags. Itsaction.ymlrunsghcr.io/google/osv-scanner-action:v2.5.0, and run 37483796939's job steps include "Pull ghcr.io/google/osv-scanner-action:v2.5.0". The# v2.3.8comment had been stale since Dependabot's sha bump (chore(ci)(deps): Bump google/osv-scanner-action/osv-scanner-action from 9fd1bcce27f67e3bd819a0a7620e332803dc43bc to f4cfcc01edc9c8b756a9b873b7a623ca674da51e #9209). It is corrected, and all threeuses:lines stay on that one sha.cmd/osv-scannerwith the same flags (goreleaser buildsosv-scanner-action). The release binaryosv-scanner_linux_amd64matched its published SHA256SUMS (edcfc41d…). The action's entrypoint is upstream'sexit_code_redirect.sh, which rewrites exit 128 (no packages) to 0.--configexplicitly on both sides. This settles dispatch assumption ②: without--config, a base lockfile staged at another path is scanned with no ledger at all.--configand--output-file:results: []ignoreUntil--configfileBecause the outcome alone cannot tell findings from errors, the helper's file-plus-outcome agreement check is what keeps the verdict closed.
The pin
The body is written once, when the PR is created and before any run exists, so the run ids are posted in the
os-dev-reportcomment on #22082, keyed by the head shas named here.Real runs (seat amendment, from the dev's report on #22082). All are
validate-deps.ymlonpull_request, against the merge baseef1fcb26a24f(themaintip):ce598b1ab737719042481(113122177520)501569be49(probe:minimist1.2.5)37719190017(113122655549)GHSA-xvch-5gv4-984h(minimist@1.2.5)3576cdc334(probe reverted)37719368398(113123226526)5473cad514(probe:minimist1.2.8, no advisory, lockfile changed)37719558844(113123838149)next@16.3.6cc98faf47a(final; same tree asce598b1ab7)37719733046(113124391631)mainatef1fcb26a24fcarries those six advisories (filed as #22148). So:37719558844;scripts-only pin is37719368398/37719733046, against that advisory-carryingmain;"A lockfile that introduces a new advisory fails": real run
501569be49is a TEMPORARY probe commit. It adds root devDependencyminimist1.2.5 (GHSA-xvch-5gv4-984h, fixed in 1.2.6) throughpnpm add -D -w. The PR squashes, and3576cdc334reverts the probe.compare=true, both scans run, and the judge fails with exactly oneerrorannotation, for GHSA-xvch-5gv4-984h (minimist@1.2.5).8fc50b7647and the 2026-10-06 database snapshot described under R1–R3:"Lockfile unchanged": real runs
ce598b1ab7(the implementation, at PR open) and3576cdc334(after the probe's revert). The two trees are identical: both ared477febb20.pnpm-lock.yamlnorosv-scanner.toml, and.github/workflows/validate-deps.ymlis in thepaths:filter, so the workflow runs on it.main's advisory state cannot reach it. That is why ascripts-only PR against amainthat carries an advisory passes here. R1 replays exactly that case."Inherited passes with a notice": real run
37719558844(above); the replays below are supplementarymainis clean today: scheduled run 37565270565 succeeded. A real PR run here cannot have a merge base that carries an advisory unlessmainis touched or a throwaway branch is made, and both are out of bounds. Following the dispatch, the step logic was replayed on real historical pairs instead. The replay worked like this:git merge-tree --write-tree BASE PRHEAD, thengit commit-tree -p BASE -p PRHEAD) in an isolated clone.run:text verbatim, as extracted from this branch's workflow. The only change was the helper's path, because the historical trees carry no copy of the helper.scan-argsverbatim through upstream's ownexit_code_redirect.shand the release binary, with outcome = exit 0 ? success : failure.run:text verbatim.The gap, named: this container's egress policy refuses
api.osv.dev. The scans therefore ran--offlineagainst a local snapshot of the OSV npm database. That snapshot is anall.zipof 230,017 records, with maxmodified2026-10-06T16:30:04Z and sha2560bd50081c140…. It was found already on this container's disk, and its provenance is otherwise unknown. Its GHSA-wq5f-xc86-pv6w (sharp, published 13:43Z) and GHSA-pqg4-j6r4-53mv (shell-quote, published 13:40Z) records are those finding card #22013 measured. The anchor lookup used the real repo-scoped listing.R1: PR #22002 as run 37483796939 saw it (the card's specimen: a
scripts-only change). Base isf0022c46c1,main's tip when the run was created (15:00:57Z). PR head is95c510eb8a.R2: PR #21951 (a real lockfile-changing PR against a
mainthat carries advisories). Base is4c49150e0c, PR head is539b0752cd. The constructed merge'spnpm-lock.yaml,osv-scanner.tomlandpnpm-workspace.yamlblobs equal those of the PR's real squash commit787104baa9.The anchor clause reads "no open issue names it yet" because #22013 is closed today. A live probe of the same listing found the open issues that name a given advisory id. It also turned up a seat board post quoting one, which is why board posts (
pm:seat) are skipped; the self-test pins both the anchor case and the board-post skip.R3: a synthetic ledger-only PR that deletes the sprintf-js exemption from
787104baa9'sosv-scanner.tomland touches no lockfile:Helper ablations (each run with
scripts/ablation-replace.mjs, which restores the file and confirms the restored blob equals HEAD)compareignores the base (if (base.has(id)) inherited.pushbecomesif (false) inherited.push). The self-test fails: 25 failed expectations over 23 cases, exit 1.f35d31ee1072= HEAD, andgit diff HEADis empty.Local verification
These gates ran at
bf15ed3831, plusce598b1ab7for the entry-guard fix. The final treed477febb20is identical atce598b1ab7and3576cdc334.node scripts/pm/dispatch-gates.mjs --commandsderived 54 commands over the actual diff, and all 54 exit 0.check:entry-guardfirst went red because the helper exported bindings and ran on import. The fix puts the dispatch behindisEntrypoint, and the gate is now green.pnpm check:pm-dispatch-gates: 1976 cases pass, in 820.5s.--ranreconciliation: 54 derived, 54 run, 0 NOT-MEASURED.npx eslint --no-inline-config --format json scripts/osv-base-relative.mjsreported 1 file, 0 errors and 0 warnings.eslint.config.mjshas noparserOptions.project), so this diff cannot change the verdict on any file it does not touch.pnpm lintbelongs to CI.Acceptance notes
mainalready carries. That advisory reads as inherited, and the notice lists both sides' package versions so the addition is visible.main's daily scan still judges it. Upstream's reporter counts occurrences instead.osv-scanner.tomlheader says the workflow "blocks on any advisory at any severity". That is still true ofmain's scan, but a PR now answers only for what it introduces.osv-scanner.tomlandscripts/check-osv-exemptions.mjsheaders cite measurements "against v2.3.8". The pinned image has been v2.5.0 since the Dependabot bump.mainstill reddens every dependency-touching PR through the unchanged "Verify OSV exemptions carry an expiry and a reason" step, which the ruling keeps as is.issues: write, which no step in it uses. The judge's anchor lookup only reads. Permissions are unchanged here.Generated by Claude Code