ci: add fix-dependabot-alerts automation#339
Merged
Merged
Conversation
Adds a custom Node remediator (tools/scripts/fix-dependabot-alerts.mjs) and a daily GitHub Actions workflow (.github/workflows/fix-dependabot-alerts.yml) that: 1. Reads open Dependabot alerts via the REST API (requires a GitHub App: DEPENDABOT_APP_ID variable + DEPENDABOT_APP_PRIVATE_KEY secret). 2. For each alert, tries 'npm update <pkg> --package-lock-only' first, then falls back to a root 'overrides' entry. 3. Verifies via the lockfile that every resolved instance is >= the advisory's first_patched_version. 4. Runs 'npm ci --ignore-scripts && npm run build && npm test' to verify; rolls back on failure with a 7-day cooldown to avoid retrying broken upgrades daily. 5. Opens a single squash PR with only the passing fixes; status taxonomy distinguishes applied / rolled_back / unfixable / no_patch / cooldown. Local validation against the current 9 open alerts: 1 of 4 packages fixed (minimatch 3.1.3 -> 3.1.5). The other 3 (qs, tar, @tootallnate/once) are correctly classified as 'unfixable' because parent semver pins (e.g. express requires qs ~6.14.0) prevent npm 'overrides' from taking effect — these need upstream parent updates. Modeled on the equivalent automation in microsoft/TypeAgent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a daily GitHub Actions automation to remediate open Dependabot security alerts for the typescript/ npm workspace by applying lockfile-only updates / overrides, verifying via lockfile inspection plus npm ci + build/test, and opening a single PR containing only passing fixes.
Changes:
- Introduces
tools/scripts/fix-dependabot-alerts.mjsto fetch/group Dependabot alerts and attempt verified remediations with rollback + cooldown tracking. - Adds
.github/workflows/fix-dependabot-alerts.ymlto run the script on a schedule / dispatch, cache rollback state, perform a final clean verification, and create/supersede a remediation PR.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| tools/scripts/fix-dependabot-alerts.mjs | Implements alert fetching, lockfile verification, update/override strategies, and rollback/cooldown tracking with build/test validation. |
| .github/workflows/fix-dependabot-alerts.yml | Schedules and orchestrates the remediation run, final clean verification, and automated PR creation via a GitHub App token. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Four fixes for valid Copilot review findings: 1. semverGte: parseSemver now captures prerelease tags; semverGte treats a prerelease as strictly less than the corresponding release per semver. Previously 1.2.3-beta.1 was accepted as satisfying first_patched_version=1.2.3, letting a vulnerable prerelease through verification. 2. attemptOverride now pins to the exact first_patched_version (was '>=X'), preventing range overrides from silently picking up unrelated major upgrades. Also detects and preserves the existing package.json indentation (2-space in TypeChat) so override commits don't reformat the whole file. 3. buildAndTest: when tests are enabled, only 'npm test' is run (which already runs 'npm run build' as its first step). 'npm run build' is only invoked explicitly in --skip-tests mode. Halves per-fix verification time. 4. Workflow final clean verification: same change — 'npm test' only when tests enabled, 'npm run build' only when skipped. Verified locally: semver edge cases pass (1.2.3-beta.1 < 1.2.3 now correctly rejected); dry-run still reports 4 actionable groups. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
robgruen
approved these changes
Jun 2, 2026
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.
Summary
Adds a custom Node remediator (
tools/scripts/fix-dependabot-alerts.mjs) and a daily GitHub Actions workflow (.github/workflows/fix-dependabot-alerts.yml) that automatically opens a single PR with verified fixes for open Dependabot security alerts intypescript/.Modeled on the equivalent automation in microsoft/TypeAgent, adapted for TypeChat's npm + workspaces layout.
This is the companion of #338, which added the missing
npmecosystem entry todependabot.ymlso Dependabot would actually surface and (where possible) auto-PR npm vulnerabilities. The current 9 open alerts are all transitive, which Dependabot can rarely fix on its own — this automation handles those cases.How it works
DEPENDABOT_APP_IDvariable +DEPENDABOT_APP_PRIVATE_KEYsecret).npm update <pkg> --package-lock-only, (b) rootoverridesentry.first_patched_version(avoids false positives from no-op installs).npm ci --ignore-scripts && npm run build && npm testafter each fix; rolls back individually on failure and records a 7-day cooldown so the same broken upgrade isn't retried daily.rm -rf node_modules out && npm ci ...) catches transitive.d.tsbreakage that the per-fix incremental build would miss.Status taxonomy
appliedrolled_backunfixableno_patchfirst_patched_versionyetskipped_cooldownLocal validation
Ran against current 9 open alerts:
npm updateunfixable: parent semver pins (e.g.expressrequiresqs ~6.14.0) cause npm to silently ignore the rootoverridesentry. These need upstream parent updates and stay in Dependabot's queue.Security notes
GH_TOKEN,GITHUB_TOKEN,NPM_TOKEN,DEPENDABOT_APP_PRIVATE_KEY) are stripped from the env before invokingnpm ci/npm run build/npm test— those steps execute code from newly-updated dependencies.actions/checkoutruns withpersist-credentials: falseso the default token isn't reachable in.git/configduring dep code execution. Push uses the App token explicitly.gh pr createto avoid the 1-hour expiry hitting long verification runs (lesson from fix(fix-dependabot-alerts): refresh app token before creating PR TypeAgent#2393).Required setup before this can run
Dependabot alerts: Read+Pull requests: Write+Contents: Writepermissions.DEPENDABOT_APP_IDvariable andDEPENDABOT_APP_PRIVATE_KEYsecret.Until those are set, the workflow will fail at the ""Generate GitHub App token"" step but will not affect anything else in the repo.
Followup
Surfaced during validation: the workspace's pre-existing
prepare → build-alllifecycle currently fails on asentiment-zodTS error unrelated to this work, which is why the script (and would-be Dependabot PRs) need--ignore-scriptsonnpm ci. Worth a separate triage issue.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com