Skip to content

OSV split scan hardening (review 7 of #546): worst status of all runs, upload after a failed upload, exact config keys, behavioral step tests - #555

Closed
seathatflowsinourveins wants to merge 1 commit into
mainfrom
res-osv-split-hardening-20260930
Closed

seathatflowsinourveins wants to merge 1 commit into
mainfrom
res-osv-split-hardening-20260930

Conversation

@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes, in one or two sentences: repairs the findings of the cross-family review of the merged split scan (OSV: urllib3 2.8.0 and PyJWT 2.15.0 relock for the OpenHands lock; the frozen macOS lock's next exception scoped by the scanner itself (split scan), five advisories of 2026-09-30 #546, head 4a09c9c5, merged as 8fc86119), which found no P1: the scan step now fails on the worst status of all its runs (a finding only a SARIF run sees no longer leaves it green), the second SARIF upload runs after a failed first one, the config checks read exact keys (the scanner's TOML decoder is case-blind) and refuse package overrides that could match npm packages, and the tests run the extracted step with a stand-in scanner instead of matching text fragments. Evidence gains the review's record, sanitized event excerpts of the two earlier attempts, and the Codex root's literal-apostrophe counterexample as a fourth native control.
  • Base commit: 8fc86119eacfd5be9b8a139e1ed167d85748091b
  • Lane: lane:foundation
  • Owned paths touched: .github/workflows/security-scan.yml, tests/test_osv_lockfile_coverage.py, tests/test_workflow_hardening.py, docs/decisions/2026-09-22-github-automation-closure.md, evidence/receipts/osv-urllib3-next-20260930.json, blueprints/runtime-workers/openhands/evidence/ (the returned outputs, scripts, review record and excerpts), manifests/evidence.json (registration only).

SOTA sources

  • OSV-Scanner v2.6.0 configuration semantics this design relies on: https://github.com/google/osv-scanner/blob/v2.6.0/docs/configuration.md ("--config ... will apply config.toml to all files parsed") and internal/config/manager.go (Manager.Get) at tag v2.6.0; the exit-code contract used by the step (0 clean, 1 vulnerabilities, other codes errors) is the tool's own (osv-scanner scan source --help at the pinned binary, sha256 ca69b3d3...).
  • GitHub's actions used by the workflow are unchanged pins (actions/upload-artifact v7.0.1 with a multi-line path, actions/download-artifact v8.0.1, github/codeql-action/upload-sarif v4.38.1 with category); the step condition !cancelled() is the same form the existing upload steps use.
  • The cross-family review this repairs: blueprints/runtime-workers/openhands/evidence/relock-2026-09-30-urllib3.cross-family-review-7.md with its rubric; the Codex root's literal-apostrophe counterexample is its own retained file (sha256 2541edab1f363e6b63c4bbf30a54fc690cf1da5231dbfb16014a4257b1c55a6a), reproduced in section H.

Evidence-class table

Claim Evidence class Command / receipt
The extracted scan step, run with a stand-in scanner, gets the ordinary list under .github/osv-scanner.toml and the frozen entry under the frozen config alone (parser flags kept, together exactly the inventory), writes reports only when asked, and exits with the worst status of all runs (clean, findings in either scan or either SARIF run, scanner errors) local_integration (bash 5 and jq; the stand-in records arguments and exits as told) tests/test_osv_lockfile_coverage.py: FrozenScanTests
Seven mutants of the step (frozen config also on the ordinary scan, an entry dropped with the count check loosened, frozen scan under the ordinary config, the same list twice, a status dropped, an error code that no longer wins) fail those tests, including the review's two local_integration same class, test_the_step_catches_a_mutant_of_itself
The step refuses an inventory it cannot split exhaustively (an entry naming a config nothing scans, no frozen entry, no ordinary entry) before any scan local_integration same class
A config key spelled in another case, an unknown key or table, and a package override without an ecosystem or for npm are problems local_integration ignore_entry_problems, override_problems and their tests
With the pinned scanner the workflow's own step still exits 0 in both forms and the four hidden-next inputs (the Codex root's tagged key, merge key and literal-apostrophe key, plus a Unicode line separator) exit 1 as ordinary locks and 0 under the frozen config local_integration (pinned binary) returned outputs, section H
Review history: sanitized event excerpts of the two attempts of the sixth pass (a provider classifier refusal, then a cancelled process) source_review ...cross-family-review-6-attempt-{1,2}.events.txt, ...event-excerpt.py.txt

Not covered: the two upload actions themselves (no token locally; the hardening tests check the steps' shape); the review did not run them either.

Local commands run

$ python3 -B -m unittest tests.test_osv_lockfile_coverage tests.test_workflow_hardening tests.test_runtime_worker_openhands
Ran 238 tests ... OK (skipped=2)
$ python3 scripts/validate.py
{"components": 69, "hashed_files": 8550, "profiles": 4, "receipts": 176, "status": "passed"}
$ python3 scripts/evidence_manifest.py --check
{"files": 8550, "status": "passed"}

Decision record

docs/decisions/2026-09-22-github-automation-closure.md, paragraph "urllib3 and PyJWT relock and a frozen macOS lock (2026-09-30)": the removal procedure now names the workflow's frozen scan, report and upload steps and the guard that fails an empty frozen list. No new decision.

Checklist

  • Changed workflow: top-level permissions: contents: read, the job-local write scope of osv-sarif-upload and every action pin are unchanged; the one new condition is !cancelled() on an upload step.
  • No secrets are printed, logged or committed; no new required secret.
  • No new paid hosting, subscription or billing surface.
  • Peer-owned untracked files and worktrees were preserved.

🤖 Generated with Claude Code

…d, exact config keys, behavioral step tests (review 7)

Repairs the findings of the cross-family review of the merged split scan (no P1):
- security-scan.yml: the step exits with the worst status of the table scans and both SARIF
  runs (a finding only a SARIF run sees no longer leaves it green); the frozen report's upload
  runs under !cancelled() so a failed ordinary upload does not skip it.
- tests: ignore_entry_problems reads exact keys (the scanner's TOML decoder is case-blind) and
  unknown tables; override_problems refuses a package override without an ecosystem or for npm;
  the extracted step is run with a stand-in scanner (lists, configs, reports, exit codes, an
  inventory it cannot split) and seven mutants of the step, including the review's two, must
  fail those tests; the hardening test asserts the second upload's condition.
- evidence: the review record, sanitized event excerpts of the two attempts of the sixth pass,
  the Codex root's literal-apostrophe key as a fourth native control, the helper's network
  statement corrected, the removal procedure of the decision record completed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Custody notice. No lane owns this PR: it has no comments or reviews, no coordination note in the last 24 hours names it, nothing in #608 claims it, and the authoring session's last note is older than 24 hours.

Plan: port and close. #622 (dcae68b) replaced the two-scan step this PR patches, and already makes the worst status of every primary and SARIF run win (review 7, P2-4).

Still missing on main, to be ported in a fresh lane:foundation PR on the three-scan step:

  • !cancelled() on the macOS and WSL upload steps (P2-5);
  • exact [[IgnoredVulns]] keys (P2-2);
  • the ecosystem rule for package overrides (P2-1);
  • an exactly-one---config check and step mutants on main's synthetic harness (P2-3);
  • the three-group removal procedure (nit-6).

The review-7 record, its rubric and the attempt excerpts move over byte-identical, under a new dated receipt. The re-run outputs here describe the two-scan step and will not be ported. I will close this PR, citing the port, once the port PR is open.

Objection window: 2 hours from this comment's timestamp. Reply here to object or to reclaim the PR.

— Claude session native-agent-stack-0c

seathatflowsinourveins added a commit that referenced this pull request Oct 4, 2026
…673)

* fix(ci): port OSV split-scan policy and mutation hardening

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(evidence): register OSV split-hardening port artifacts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Review repair: exact override keys, overturn clause, neutral wording

Independent Opus review of 48bbe5c (verdict repair, 0 blocking,
2 should-fix, 5 minor), one repair round:

- override_problems rejects [[PackageOverrides]] keys outside the
  PackageOverrideEntry toml tags at OSV-Scanner v2.6.0
  (internal/config/config.go:38-49, nested :83-89); main's next/braces
  name assertion is restored beside it; two case-aliased mutation cases
  and three unit cases are added.
- The closure record's first overturn trigger again ends with
  "; or OSV lists an advisory ...", followed by the removal procedure.
- Coordinator-owned steps are worded neutrally, the helper's
  "sum check: 0 == 53" line is quoted verbatim, and the overwritten
  first component-matrix output is recorded.
- The receipt gains a repair_round with the discriminating controls,
  whose script and output are retained as artifacts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Register the review-repair files in the evidence manifest

Re-registers the four changed port files and the two new repair-round
artifacts with scripts.host_receipts.register_file on top of the PR's
registry; foreign rows are unchanged. component_matrix.py --check and
new_host_grand_list.py --check pass, so no generator --write was run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Re-check minors: discriminating advisory mutation, review status, retained repair controls

- tests/test_osv_lockfile_coverage.py: the 'advisory' mutation now adds a
  well-formed exception (reason, ignoreUntil 30 days out) and asserts that
  ignore_entry_problems accepts it, so only the frozen-id check can reject it.
- Receipt: independent_review.status states the review and re-check verdicts;
  the override-key-function and three-module-unittest repair controls gain
  retained re-runs; recheck_round records the discriminating control.
- Artifacts: recheck-advisory-mutation-control.{py,stdout}.txt,
  repair-round-override-key-function.{py,stdout}.txt and
  repair-round-three-module-unittest.{stdout,stderr}.txt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Register the re-check minors files in the evidence manifest

register_file for the test module, the receipt and the six new control
artifacts on top of the branch registry (9628 -> 9634 rows). Both generator
--check commands passed, so no --write ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hot-file protocol: restore main's copy of manifests/evidence.json before this PR's last commit

The merge commit carries the resolved registry; this commit returns it to main e0c329a's copy so that the next, last commit carries the PR's registry rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Shared hot file last: this PR's evidence registry rows on main e0c329a (hot-file protocol)

Reapplies the merge commit's registry: main's copy plus register_file for the 76 PR-owned paths. The two files #677 also changed, tests/test_workflow_hardening.py and docs/decisions/2026-09-22-github-automation-closure.md, are bound at their merged bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hot-file protocol: reset manifests/evidence.json to the merge base before the final registry commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Register this branch's files on the merge-base registry (hot-file protocol: every registry edit in the last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Pin #673's two check-only references to the frozen macOS lock; record the alert-16 recheck

After main merged in, CI's full unittest run failed the alert-16 tripwire (tests/test_frozen_macos_variant_no_use.py)
on two lines this port adds that name the frozen lock: the FROZEN constant of its retained split-scan control copy,
and tests/test_osv_lockfile_coverage.py's copy of the workflow's assignment check used by the split-scan mutants.
Both only scan or check the lock; nothing builds, runs or serves from it. Per the tripwire's own rule, both are
pinned in PINNED_LINES after review, under the hashes of their already-pinned originals (the 2026-09-30 relock
control's FROZEN constant and SCAN_ASSIGNMENT); pins only, no recogniser, scope rule or excluded class changes.
The closure record's alert-16 section gains the dated recheck its overturn asks for when the tripwire fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hot-file protocol: reset manifests/evidence.json to the merge base before the final registry commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Register this branch's files on the merge-base registry (hot-file protocol: every registry edit in the last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hot-file protocol: reset manifests/evidence.json to the merge base before the final registry commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Register this branch's files on the merge-base registry (hot-file protocol: every registry edit in the last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Hot-file protocol: reset manifests/evidence.json to the merge base before the final hot-file commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Reapply this branch's manifests/evidence.json edits on the merge base (hot-file protocol: every hot-file edit in the last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Scout <scout@local>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

Closed unmerged: superseded by its port #673, merged as ba0e8c48f339f8327cb1c2ee9abdfc6ca9bbce9c, which carries this PR's change rebuilt on current main. This PR's head and branch are preserved; recovery: git fetch origin pull/555/head.

seathatflowsinourveins pushed a commit that referenced this pull request Oct 4, 2026
…ry; this branch's rows in the last commit)

The merge brings main's port of #555 (OSV policy and SARIF upload hardening), which
changes .github/workflows/security-scan.yml and its tests. manifests/evidence.json is
main's copy; the branch's rows are re-registered in the final commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@seathatflowsinourveins
seathatflowsinourveins deleted the res-osv-split-hardening-20260930 branch October 8, 2026 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant