You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Each of these was checked against this repo, because the approach rests on them:
Claim
Status
Alerts are readable from a workflow with no PAT
✅ GITHUB_TOKEN supports vulnerability-alerts: read (workflow syntax). Read-only, which is all we need.
There is no dependabot_alert workflow trigger
✅ Webhook event only, not in the events reference. So this is a scheduled sweep, not event-driven.
PRs can be disabled while alerts stay on
✅ Two independent toggles. GET /repos/{o}/{r}/automated-security-fixes currently returns {"enabled":true,"paused":false}; DELETE on that path turns the PRs off. GET /repos/{o}/{r}/vulnerability-alerts returns 204 and is unaffected.
✅ Needed for the range check below; no new dependency.
Group alerts by bump, not by advisory
Alerts are per-advisory. At the time of writing, 7 open alerts across 3 packages: fast-uri ×4 (package-lock.json, high, fixed in 3.1.6), qs ×2 (package-lock.json, medium, fixed in 6.16.0), browserslist ×1 (clients/tui/package-lock.json, high/dev, fixed in 4.28.7). A 1:1 mapping would file seven issues for three overrides entries. So:
Group by (package, manifest_path, first_patched_version) — one issue per bump, listing every GHSA it clears.
The issue body carries a machine-readable marker naming every GHSA covered (<!-- dependabot-alerts: GHSA-…,GHSA-… -->). That marker is the idempotency key.
A new alert for a package with an open issue gets a comment on that issue, not a second issue, and the marker is rewritten to include it.
Verify against v2/main before filing
GitHub computes the dependency graph, and therefore every alert, from the default branch (main). The sweep does not trust the alert's applicability — it re-checks the vulnerable range against v2/main's own lockfile before filing:
git show origin/v2/main:<manifest_path># resolve the installed version# then: semver.satisfies(installed, alert.security_vulnerability.vulnerable_version_range)
Satisfies → real on the branch we ship from. File.
Does not satisfy → already fixed on v2/main, alert is waiting on a milestone merge to close. Skip silently.
Manifest absent on v2/main → log and skip.
Run today, this confirms live exposure: origin/v2/main carries fast-uri@3.1.5 and qs@6.15.3, both in range.
Blind spot, stated plainly: a vulnerable dependency introduced on v2/main and not yet merged to main produces no alert at all. No approach that consumes GitHub's alerts avoids this. The release-time npm audit fix from #2231 is the second signal that partially covers it; a scheduled npm audit --audit-level=high over v2/main's lockfiles would close it fully and is a separable follow-up.
Schedule and permissions
on:
schedule: [{ cron: "17 6 * * *" }] # daily; alerts are not minute-sensitiveworkflow_dispatch:
permissions:
contents: readissues: writevulnerability-alerts: read
Daily, not hourly — with Dependabot's PRs off there is no mergeable-against-main artifact and no window to race, so #2060's merge guard is unnecessary.
The only thing GITHUB_TOKEN cannot do is write the board card (org project → fine-grained PAT or App token with organization projects: write). Degrade gracefully: if the project write fails or the secret is absent, still create the issue with labels and milestone and let the next /issue-triage sweep board it — its documented exception moves an unboarded-but-milestoned issue straight into Todo. The PAT is an optimization, not a prerequisite.
Issue shape
Field
Value
Title
chore(deps): bump `<pkg>` to `<first_patched>` in `<manifest>` (<n> advisories)
Labels
v2, chore, dependabot
Milestone
current open milestone with the nearest due date, resolved at runtime
Todo, not Incoming — arriving through this pipeline is the approval. Priority High is a standing rubric override (a routine bump scores Medium; these must not sit). Record the override in the body.
The body states, from the alert plus the lockfile probe: every GHSA / CVE with severity and summary; installed version on v2/main and the version to reach; runtime vs development scope; direct vs transitive — a transitive fix is an overrides entry per Dependency placement, never npm audit fix, and all three of today's packages are transitive; links to the alert pages.
Turning security PRs off
DELETE /repos/modelcontextprotocol/inspector/automated-security-fixes (or Settings → Code security). Because it is a repo setting, it can be re-enabled from the UI without a commit — so the sweep asserts GET …/automated-security-fixes still reports disabled and fails loudly if not. That is this design's analogue of #2060's merge guard: one API call instead of a required status check plus a ruleset change.
Acceptance
Dependabot opens no security PRs; automated-security-fixes reports disabled and vulnerability-alerts reports enabled.
The sweep files one issue per bump, not per advisory: today's 7 alerts produce exactly 3 issues, each naming every GHSA it clears.
An alert whose vulnerable range no longer matches v2/main's lockfile produces no issue.
Each issue is labeled v2 + chore + dependabot, carries the current milestone, and sits on board Add tab and approval flow for server -> client sampling #28 in Todo at Priority High — and when the project write is unavailable, it is still created labeled and milestoned.
A second run the same day is a complete no-op.
A new advisory for a package with an open issue lands as a comment, not a new issue.
The run fails loudly if Dependabot security PRs have been re-enabled.
AGENTS.md and .github/dependabot.yml's comment block describe the alert-driven flow.
Sub-issue of #2229 — the alert-consuming half. (#2231 covers the other half:
npm audit fixat release time and the monthlynpm outdatedissue.)Turn Dependabot security-update PRs off. Keep its alerts on. Drive our own issues from the alerts, and write the fix ourselves against
v2/main.Verified mechanics
Each of these was checked against this repo, because the approach rests on them:
GITHUB_TOKENsupportsvulnerability-alerts: read(workflow syntax). Read-only, which is all we need.dependabot_alertworkflow triggerGET /repos/{o}/{r}/automated-security-fixescurrently returns{"enabled":true,"paused":false};DELETEon that path turns the PRs off.GET /repos/{o}/{r}/vulnerability-alertsreturns204and is unaffected.dependency.package.name,dependency.manifest_path,dependency.scope,security_advisory.{ghsa_id,cve_id,severity,summary},security_vulnerability.{vulnerable_version_range,first_patched_version.identifier}.semveris already resolvable at the repo rootGroup alerts by bump, not by advisory
Alerts are per-advisory. At the time of writing, 7 open alerts across 3 packages:
fast-uri×4 (package-lock.json, high, fixed in 3.1.6),qs×2 (package-lock.json, medium, fixed in 6.16.0),browserslist×1 (clients/tui/package-lock.json, high/dev, fixed in 4.28.7). A 1:1 mapping would file seven issues for threeoverridesentries. So:(package, manifest_path, first_patched_version)— one issue per bump, listing every GHSA it clears.<!-- dependabot-alerts: GHSA-…,GHSA-… -->). That marker is the idempotency key.Verify against
v2/mainbefore filingGitHub computes the dependency graph, and therefore every alert, from the default branch (
main). The sweep does not trust the alert's applicability — it re-checks the vulnerable range againstv2/main's own lockfile before filing:v2/main, alert is waiting on a milestone merge to close. Skip silently.v2/main→ log and skip.Run today, this confirms live exposure:
origin/v2/maincarriesfast-uri@3.1.5andqs@6.15.3, both in range.Blind spot, stated plainly: a vulnerable dependency introduced on
v2/mainand not yet merged tomainproduces no alert at all. No approach that consumes GitHub's alerts avoids this. The release-timenpm audit fixfrom #2231 is the second signal that partially covers it; a schedulednpm audit --audit-level=highoverv2/main's lockfiles would close it fully and is a separable follow-up.Schedule and permissions
Daily, not hourly — with Dependabot's PRs off there is no mergeable-against-
mainartifact and no window to race, so #2060's merge guard is unnecessary.The only thing
GITHUB_TOKENcannot do is write the board card (org project → fine-grained PAT or App token withorganization projects: write). Degrade gracefully: if the project write fails or the secret is absent, still create the issue with labels and milestone and let the next/issue-triagesweep board it — its documented exception moves an unboarded-but-milestoned issue straight into Todo. The PAT is an optimization, not a prerequisite.Issue shape
chore(deps): bump `<pkg>` to `<first_patched>` in `<manifest>` (<n> advisories)v2,chore,dependabotTodo, not Incoming — arriving through this pipeline is the approval. Priority
Highis a standing rubric override (a routine bump scores Medium; these must not sit). Record the override in the body.The body states, from the alert plus the lockfile probe: every GHSA / CVE with severity and summary; installed version on
v2/mainand the version to reach;runtimevsdevelopmentscope; direct vs transitive — a transitive fix is anoverridesentry per Dependency placement, nevernpm audit fix, and all three of today's packages are transitive; links to the alert pages.Turning security PRs off
DELETE /repos/modelcontextprotocol/inspector/automated-security-fixes(or Settings → Code security). Because it is a repo setting, it can be re-enabled from the UI without a commit — so the sweep assertsGET …/automated-security-fixesstill reports disabled and fails loudly if not. That is this design's analogue of #2060's merge guard: one API call instead of a required status check plus a ruleset change.Acceptance
automated-security-fixesreports disabled andvulnerability-alertsreports enabled.v2/main's lockfile produces no issue.v2+chore+dependabot, carries the current milestone, and sits on board Add tab and approval flow for server -> client sampling #28 in Todo at Priority High — and when the project write is unavailable, it is still created labeled and milestoned.AGENTS.mdand.github/dependabot.yml's comment block describe the alert-driven flow.