Skip to content

security alerts: try the override fix itself, on one rolling pull request - #571

Merged
Nawid3333 merged 3 commits into
mainfrom
ci/security-overrides
Oct 24, 2026
Merged

Nawid3333 merged 3 commits into
mainfrom
ci/security-overrides

Conversation

@Nawid3333

@Nawid3333 Nawid3333 commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

An alert Dependabot cannot fix became an issue for the owner, and the fix was then made by hand. #564 was such a case: floors in pnpm-workspace.yaml's overrides, and the lockfile rewritten. security-alerts.yml now tries that fix itself where a floor makes it, and falls back to today's issue where it cannot. This is the third update gap found while checking what Dependabot does not cover (#565, #566).

How it works

Three jobs, so that the job that rewrites the security-relevant manifests holds no write token:

  • check (today's job, extended) plans the floors with tools/security-overrides.mjs: one floor per package and major the lockfile holds vulnerable, ^ the newest first patched version. It declines an alert, with the reason written into the issue, when:

    • there is no patched version;
    • the fix is a new major;
    • the package is pnpm-patched;
    • a parent-scoped (web-ext>pkg) or unreadable override governs it;
    • main has the floor already while the lockfile is still vulnerable.

    The alerts it takes stay out of the issues: they are subtracted from both $new and $list, because an alert listed in an issue's marker is never raised again.

  • install has only contents: read, and no token appears in it. It runs pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile with the floors, so no package code is ever on disk. Then verify checks three things: every alert taken is fixed, every floor holds, and nothing but the floored packages moved. If pnpm says no version fits (ERR_PNPM_NO_MATCHING_VERSION, ETARGET), those alerts are demoted to issues. Any other failure fails the run, and the report job opens "Security override route failed". Nothing is left silent.

  • publish, the only writer:

    • builds the commit through the API, on the main the plan was made on (if main moved meanwhile, the next day's run takes it);
    • keeps ONE rolling pull request, "Security fixes: override floors", on security/overrides;
    • starts CI and the dependency review on it. Runs that never ran do not count as covering the head: a pull_request run of a pull request this token opened waits for an approval, action_required (update PRs: a run that never ran decides nothing #570).

    A pull request closed unmerged by hand hands its alerts back as issues; this workflow's own closes are marked closed-by-run.

  • update-prs.yml reports on it as the kind security: only pnpm-workspace.yaml and pnpm-lock.yaml may change, its dependency review must pass, and there is no 3-day wait, since it is a security fix. On the update-branch path the dependency review is started again. ci.yml's hand-off covers security/.

  • The fsaunpack lockfile stays on the issue route.

Tested

  • Replay on real data. I took the commit before deps: undici 7.30.1 / 8.12.3 and serialize-javascript 7.1.3 (Dependabot #73-#79) #564 and its seven alerts (Reminder: after git pull, run pnpm install on your PC #73–fix(background): a player whose page reloaded while it started is no player of the new page #79), and ran the route on them:

  • Unit tests (tests/unit/securityOverrides.test.mjs, 40), covering: range parsing; the lockfile readers (the pnpm-12 first document, peer suffixes, aliases); every plan and decline rule; the edit (byte for byte against the real pnpm-workspace.yaml, CRLF and quotes kept); verify (survivors, unmet floors, churn per major, prereleases fail closed); and the bundle steps. The eight cases from a glm review fail without their fixes. Whole suite: 3080 passed.

  • Workflow tests in WSL (verify:linux workflows, which also ran actionlint, shellcheck and zizmor):

    • security-alerts.test.sh runs the real planner in seven new scenarios: an alert taken (no issue); one taken and one declined in the same package (the issue lists only the declined one, with its reason); an owner-closed pull request (its alert back to an issue); one this workflow closed (no decline); an alert an issue lists already (stays there); the open pull request read only for its alerts' states; a push (no plan). The old scenarios are unchanged.
    • update-prs-decide.test.sh: 722 checks, 0 failed, the security kind's cases among them.
    • new security-overrides-demote.test.sh runs publish's demote step: an issue with the marker and a row per alert, an open rolling pull request marked closed-by-run and closed, alerts joining an open issue's marker. With the step's first filter (.[] on plan.json, which is an object), all of it fails.
    • security-alerts.test.sh also covers a hand-closed pull request whose text lost its marker: a warning, since its close hands nothing back.
  • A second round (glm's final review and CodeQL, fixed in the second commit):

    • the demote filter above;
    • a deterministic failure now demotes every alert the run took;
    • install no longer checks out a ref read from an artifact: check and install both take the run's commit, and install refuses a plan made on another;
    • a run that steps aside because main moved says so in its summary;
    • the no-push case compares with the branch's own tree;
    • the CLI dispatches through a table.

    One finding did not hold: that update-prs.yml never runs for this branch. Runs the token starts send no workflow_run, so ci.yml's hand-off starts it, and that now covers security/.

  • glm drafted the module, the jobs and the map of the existing workflow; its reviews and mine found and fixed these:

    • the alert shape;
    • a --paginate --jq filter fed a page;
    • a heredoc that broke the YAML;
    • a transient failure that was silent;
    • action: none floors that made an empty pull request;
    • a CI dispatch that action_required runs would have suppressed;
    • unpinned actions.

Not established yet: the jobs in Actions. A manual run after the merge, with no alert open today, takes the idle path: check uploads the plan artifact and publish downloads it to see that nothing is to close. That shows whether the new actions/download-artifact v8.0.2 reads what upload-artifact v7.0.2 writes. The full route only runs when an alert Dependabot cannot fix comes in.

🤖 Generated with Claude Code

Nawid3333 and others added 2 commits October 24, 2026 04:06
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An alert Dependabot cannot fix became an issue for the owner, and the fix
was made by hand (#564: override floors in pnpm-workspace.yaml, the
lockfile rewritten). security-alerts.yml now tries that fix itself where
a floor makes it, in three jobs:

- check plans the floors (tools/security-overrides.mjs: one per package
  and major the lockfile holds vulnerable, ^ the newest first patched
  version; declined, with the reason in the issue, when there is no
  patched version, the fix is a new major, the package is pnpm-patched,
  a parent-scoped or unreadable override governs it, or main has the
  floor already while the lockfile is still vulnerable). The alerts it
  takes stay out of the issues, out of both $new and $list.
- install has contents: read and no token: pnpm install
  --lockfile-only --ignore-scripts with the floors, then verify (every
  alert taken fixed, every floor holding, nothing else moved). pnpm
  saying no version fits demotes the alerts to issues; any other failure
  fails the run (a report issue), never silently.
- publish, the only writer, commits through the API on the planned main,
  keeps ONE rolling pull request on security/overrides, and starts CI
  and the dependency review on it. A pull request closed unmerged by
  hand hands its alerts back as issues; this workflow's own closes are
  marked closed-by-run.

update-prs.yml reports on it as the kind security (only those two
files, its dependency review must pass, no 3-day wait); ci.yml's
hand-off covers security/.

Replayed on the state before #564 with its seven alerts: the plan
writes the same four floors, pnpm writes the same lockfile (the order of
two keys in its overrides copy aside), verify passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread tools/security-overrides.mjs Fixed
Comment thread tools/security-overrides.mjs Fixed
- The demote step read plan.json's alerts with .[] (plan.json is an
  object): the first real demote would have died before raising any
  issue. .alerts[], and a test of the step (security-overrides-
  demote.test.sh) that fails with the old filter.
- A deterministic install failure demotes every alert the run took (no
  lockfile came out, so none publishes), not only those pnpm's log named.
- check and install both take the run's own commit; install no longer
  checks out a ref read from the artifact (CodeQL: untrusted checkout,
  cache poisoning) and refuses a plan made on another commit.
- A run that steps aside because main moved says so in its summary.
- A pull request closed by hand whose text lost its alerts marker is
  warned about, as its close then hands nothing back.
- The no-push case compares with the branch's own tree.
- The CLI dispatches through a table (CodeQL: user-controlled bypass).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Nawid3333
Nawid3333 merged commit 3689a0a into main Oct 24, 2026
22 checks passed
@Nawid3333
Nawid3333 deleted the ci/security-overrides branch October 24, 2026 02:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants