agentleFS
SentryKnown publishergetsentry/vanguard/.pi/skills/patch-security-advisories/SKILL.md

patch-security-advisories

Skill38 starsChanged 6 months agoApache-2.0View on GitHub

Patches open Dependabot security advisories in this repo (vanguard) by carefully bumping transitive dependencies through pnpm.overrides and pinning every version in package.json. Use when asked to "patch security advisories", "bump security deps", "look at open security PRs", "fix dependabot alerts", "review security advisories", or "pin down versions". Knows the vanguard-specific gotchas — scoped overrides for major-jump packages, why Dependabot's auto-PRs keep failing on this repo, and how to verify with the local docker postgres.

  • Installs packages
  • Commits and pushes
  • In this repositoryOne other file it gives its agents.

The file

We split this skill into the rules it gives an agent

8 rules. About 0 are common, 2 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use this playbook when the user asks to address open security advisories or unpin/pin dependencies on getsentry/vanguard.

    line 8
  2. Very specific:

    Use the resulting versions verbatim.

    line 70
  3. Very specific:

    Rule: if the vulnerability range is scoped to one major line (e.g.

    line 96
  4. Very specific:

    When the patched version crosses a major (e.g.

    line 114
  5. Distinctive:

    If a vulnerable version still appears: your override is wrong (probably needs scoping, or a different parent dep is requesting an explicit …

    line 138
  6. Very specific:

    If existing Dependabot PRs (e.g.

    line 160
  7. Very specific:

    Commit with the commit skill — single subject under 72 chars, body that lists each advisory with its GHSA ID, notes any scoped overrides, …

    line 166
  8. Distinctive:

    Before declaring done, confirm:

    line 179

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Patch open Dependabot security advisories on vanguard

Use this playbook when the user asks to address open security advisories or unpin/pin dependencies on getsentry/vanguard. The flow has been validated end-to-end on this repo and bakes in the gotchas that broke previous Dependabot PRs.

Step 0: Inventory before touching anything

Always present a written list and get explicit confirmation before changing files. The user expects to see scope before any commit happens.

# 1. Open Dependabot alerts (the source of truth for "what's vulnerable")
gh api /repos/getsentry/vanguard/dependabot/alerts --paginate \
  -q '.[] | select(.state == "open") | {
    number, severity: .security_advisory.severity,
    package: .dependency.package.name,
    summary: .security_advisory.summary,
    ghsa: .security_advisory.ghsa_id,
    vulnerable_range: .security_vulnerability.vulnerable_version_range,
    patched: .security_vulnerability.first_patched_version.identifier
  }'

# 2. Open PRs that may already address them
gh pr list --state open --limit 50 \
  --json number,title,headRefName,statusCheckRollup,mergeable

# 3. For each vulnerable package, find who pulls it in
pnpm why <package>

Heads-up: the dependabot/alerts API only lists advisories Dependabot has already published for the repo. The Dependency Review GitHub Action that runs on every PR (.github/workflows/dependency-review.yml) can flag fresh advisories with fail-on-severity: high before they appear in the API. After pushing the PR, run gh pr checks <PR> and inspect any dependency-review failure log — it has the format package.json » <pkg>@<version> – <summary> (high severity) ↪ <GHSA-URL>. If found, fold it into the same PR.

For each vulnerable package, classify:

  • Direct dep (listed in package.json) → bump in package.json.
  • Transitive dep (only in lockfile) → fix via pnpm.overrides. Vanguard's advisories are almost always transitive.

Step 1: Confirm scope with the user

Report back with:

  • Table of open advisories: package, current, patched, parent (from pnpm why), existing PR (if any).
  • List of open PRs touching deps with current CI status.
  • Count of unpinned versions in package.json (grep -cE '"\^|"~' package.json).
  • Proposed plan (single PR with all fixes + pinning) + risks (major-jump overrides like uuid v8 → v11).

Do not proceed without a "go".

Step 2: Branch + edit package.json

git checkout -b chore/security-pin-deps

Pin every direct dependency

Strip every ^ and ~ from dependencies, devDependencies, and pnpm.overrides. Pin to the version currently installed (from pnpm-lock.yaml), not to latest.

Get the installed versions in one shot:

pnpm list --depth 0 --json | jq -r '.[0]
  | (.dependencies // {}), (.devDependencies // {})
  | to_entries[] | "\(.key)\t\(.value.version)"' | sort

Use the resulting versions verbatim. Common discrepancies: @types/node resolves higher than declared, so pin to the actual resolved version.

Add pnpm.overrides for each transitive advisory

In package.json, under pnpm.overrides, add an entry for each vulnerable transitive dep, set to the patched version.

"pnpm": {
  "overrides": {
    "form-data": "4.0.4",
    "axios": "1.15.0",
    "rollup": "4.60.2",
    "qs": "6.15.2",
    "ws": "8.20.1",
    "uuid": "11.1.1",
    "brace-expansion@5": "5.0.6"   // scoped — see gotcha below
  }
}

🚨 Gotcha: scope range-restricted overrides

A global override forces every transitive instance to that version. If the package has multiple major lines in the tree and older majors are still in active use by other deps, a global pin will break them.

Concrete example from this repo: A global "brace-expansion": "5.0.6" override breaks minimatch@9, because minimatch@9 calls brace_expansion.default() — a default export that v5 removed. This is the exact reason Dependabot PRs for brace-expansion keep failing CI on this repo.

Rule: if the vulnerability range is scoped to one major line (e.g. >= 5.0.0, < 5.0.6), scope the override too:

"brace-expansion@5": "5.0.6"   // only affects v5 consumers

pnpm supports the <name>@<major> syntax in overrides keys.

When to apply scoping (decision table):

SituationOverride syntax
Vuln spans the entire installed range, no API breakage"pkg": "x.y.z" (global)
Vuln is in one major line only, older majors coexist in tree"pkg@<major>": "x.y.z" (scoped)
Patched version drops APIs older deps still usescoped override + verify with pnpm typecheck

🚨 Gotcha: major-jump overrides

When the patched version crosses a major (e.g. uuid 8.3.2 → 11.1.1), verify the upgrade is API-compatible with the actual consumer:

find node_modules/.pnpm/<consumer>* -name "*.js" | xargs grep -l "<package>" | head -5
grep -n "<package>" <file>   # inspect actual usage

For uuid on vanguard, the only runtime caller is remix-auth-oauth2 using uuid.v4(), which is API-stable across v8/v9/v11. Safe.

Step 3: Install + verify lockfile

pnpm install

Confirm patched versions are in place and old ones are gone:

for pkg in <vuln-package-1> <vuln-package-2>; do
  echo "=== $pkg ==="
  grep -E "^\s+${pkg}@" pnpm-lock.yaml | sort -u
done

If a vulnerable version still appears: your override is wrong (probably needs scoping, or a different parent dep is requesting an explicit different version).

Step 4: Run the full verification suite

# Local Postgres is required for tests
docker-compose up -d

pnpm typecheck      # tsc -b after react-router typegen
pnpm test           # migrates test DB + runs Vitest (163 tests expected to pass)
pnpm build          # react-router build
pnpm exec vp check  # oxlint + oxfmt

Vanguard-specific notes:

  • pnpm test requires the local postgres container; start it with docker-compose up -d first.
  • vp check will flag any unrelated unstaged files in the working tree (e.g. a stray index.html at the repo root). Inspect what it flagged — if it's not in your diff, it's not your problem.
  • A typecheck failure mentioning brace_expansion_1.default is not a function means you have the unscoped brace-expansion override — switch to brace-expansion@5.

Step 5: Close superseded PRs + commit + PR

If existing Dependabot PRs (e.g. lockfile-only bumps of ws, brace-expansion) are now redundant:

gh pr close <PR-number> --comment "Superseded by #<our-PR>, which applies the fix via pnpm.overrides alongside the other open advisories."

Commit with the commit skill — single subject under 72 chars, body that lists each advisory with its GHSA ID, notes any scoped overrides, and lists what was verified.

git add package.json pnpm-lock.yaml
git commit -m "chore(deps): patch <N> medium-severity advisories and pin versions" \
  -m "<detailed body>"
git push -u origin chore/security-pin-deps

gh pr create --base main --title "<same subject>" --body "<body with advisory table + verification + supersedes list>"

Output checklist

Before declaring done, confirm:

  • Every open Dependabot alert in the report has a corresponding override or direct bump.
  • No ^ or ~ remains in package.json (grep -E '"\^|"~' package.json returns nothing).
  • pnpm typecheck exits 0.
  • pnpm test shows all tests passing.
  • pnpm build exits 0.
  • vp check flags only files unrelated to the diff.
  • Lockfile no longer contains the vulnerable versions.
  • Superseded Dependabot PRs are closed with a comment.
  • Commit body lists every GHSA ID patched.

Reference: vanguard's tech context

  • Package manager: pnpm 10.x (enforced via preinstall hook).
  • Lockfile: pnpm-lock.yaml (committed). Always update via pnpm install, never edit by hand.
  • Test DB: local Postgres at localhost:5432 via docker-compose.yml.
  • CI: .github/workflows/ci.yml runs vp check, typecheck, and Vitest with a service-container postgres.
  • Dependabot config: .github/dependabot.yml (groups not configured — alerts arrive one PR at a time, which is why bundling them ourselves is the right move).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.