security-update
Skill4 starsChanged 28 days agoISCView on GitHub
Safely patch vulnerable npm/pnpm packages in this pnpm workspace. Use when a security audit (pnpm audit) reveals vulnerable packages, when a dependency has a known CVE, or when asked to update or patch a specific vulnerable package. For routine version currency (not a CVE), use the dependency-update skill.
- Installs packages
In this repository7 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- context-managerSkill
- dependency-updateSkill
- document-writingSkill
- engineering-terminologySkill
- translation-expertiseSkill
- web-browsingSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. About 0 are common, 12 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈12
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Run the audit and note the vulnerable package name, version range, which direct dependency pulls it in, and the recommended safe version:
- Distinctive: line 20
Before applying any fix, verify the target version was published > 10,080 minutes ago (7 days).
- Distinctive: line 28
Do not proceed: if the version is younger than 10,080 minutes.
- Distinctive: line 52
Do not update the catalog if the parent version is younger than 10,080 minutes.
- Distinctive: line 56
Check the parent's changelog/release notes for any breaking changes
- Distinctive: line 70
Use only when Step 3 is not possible: the parent requires a major bump, no fix has been released in the parent, or the vulnerable package …
- Very specific: line 97
Write the entry directly in the overrides section of pnpm-workspace.yaml:
- Very specific: line 106
Use the narrowest version specifier possible (e.g.
- Distinctive: line 107
Use a bounded target specifier so future major versions cannot resolve accidentally:
- Very specific: line 108
Prefer ^safe-version for normal semver packages when staying within the same major is safe
- Very specific: line 109
Use >=safe-version <next-major when the lower bound must be explicit
- Distinctive: line 110
Use an exact version when compatibility is uncertain, the package is pre-1.0, or the package does not follow semver reliably
- Distinctive: line 111
Check existing overrides first — do not create duplicates
- Distinctive: line 137
If the install runs in a non-interactive or frozen-by-default environment, use the explicit lockfile update path:
- Very specific: line 150
If you remove incidental lockfile noise by editing hunks, immediately rerun both commands above.
- Distinctive: line 154
Run all checks in order. Stop at the first failure and fix before continuing.
- Distinctive: line 186
If the current branch is main, create a feature branch first:
≈ “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.
Files
Security Update
Workflow
1. Identify Vulnerable Package
Run the audit and note the vulnerable package name, version range, which direct dependency pulls it in, and the recommended safe version:
pnpm audit2. Check Safe Version Age (minimumReleaseAge)
Before applying any fix, verify the target version was published > 10,080 minutes ago (7 days). This guards against package hijacking / dependency confusion attacks.
Two enforcement layers exist.
pnpm-workspace.yamlalready setsminimumReleaseAge: 10080, sopnpm installitself refuses to resolve any package version younger than 7 days. The script below is a complementary pre-check that gives a human-readable age report before you write anything to the workspace file. Keep both: the script stops you writing a too-new version; the workspace setting stops you installing one. Note thatpnpm audit --fix(Step 4a) can punch a hole in this by appending tominimumReleaseAgeExclude— see Step 4a.
node .claude/skills/security-update/scripts/check_release_age.mjs <package-name> <target-version>Do not proceed if the version is younger than 10,080 minutes. Pick the next older safe version that still resolves the vulnerability.
3. Try Direct Parent Upgrade First
Always attempt this before adding an override. Upgrading the parent is cleaner and avoids override sprawl.
a. Find which direct dependency pulls in the vulnerable package:
pnpm why <vulnerable-package>b. Check the current and latest version of the parent:
pnpm outdated <parent-package>c. Choose the target parent version and verify its age before editing the catalog:
node .claude/skills/security-update/scripts/check_release_age.mjs <parent-package> <target-parent-version>Do not update the catalog if the parent version is younger than 10,080 minutes. Pick an older safe parent version, or use Step 4 if no aged parent version resolves the vulnerability.
d. Determine if upgrading the parent to its latest minor/patch resolves the vulnerability without breaking changes:
- Check the parent's changelog/release notes for any breaking changes
- Confirm the new parent version ships with the safe sub-dep version
- The parent update must be semver-compatible (no major version bump)
e. If safe, update the parent version range in pnpm-workspace.yaml (the catalog section), then run:
pnpm installf. Run pnpm test:coverage to confirm the upgraded parent introduces no runtime regressions — if tests fail, the upgrade is not safe, so fall back to Step 4. If pnpm install itself fails because a transitive dependency shipped by the new parent is younger than 10,080 minutes (minimumReleaseAge enforcement), either choose an older parent version whose transitive dep has aged past the window, or abandon the parent-upgrade path and use a pnpm override (Step 4) targeting the sub-dep directly. Otherwise proceed to Step 5: Validate.
4. Fallback: pnpm Overrides
Use only when Step 3 is not possible: the parent requires a major bump, no fix has been released in the parent, or the vulnerable package has no identifiable direct parent.
4a. Use pnpm audit --fix as a starting point
pnpm audit --fix auto-writes override entries into pnpm-workspace.yaml. Run it, then review and consolidate the output before proceeding — do not treat it as a finished fix.
pnpm version note: This workspace uses pnpm 12.x.
pnpm audit --fixdefaults to--fix override;--fix updatere-resolves the lockfile instead of adding overrides.-i/--interactiveand--ignore-unfixableare also available. Checkpnpm audit --helpbefore relying on a flag.
pnpm audit --fixKnown problems with raw --fix output:
- Redundant range entries — when multiple packages depend on different version ranges of the same dep,
--fixwrites a separate override per range (e.g.qs@>=6.11.1 <=6.15.1: '>=6.15.2'andqs@<6.11.1: '>=6.11.1'). Consolidate these into the fewest entries that still cover all vulnerable ranges. - Lockfile not updated —
--fixonly writespnpm-workspace.yaml. Always runpnpm installafterwards to apply the overrides topnpm-lock.yaml. - Over-broad specifiers —
--fixsometimes writespackage: '>=safe'without a range qualifier. Narrow these where possible to limit blast radius. minimumReleaseAgeExcludemutation (defeats the age gate) — becauseminimumReleaseAge: 10080is set,--fixautomatically appends each overridden package tominimumReleaseAgeExcludeso the install proceeds immediately, bypassing the 7-day safety window this skill exists to enforce. After running--fix, diffpnpm-workspace.yamland remove anyminimumReleaseAgeExcludeentries--fixadded — this workspace has no permanent exclude entries. Then run Step 2 (check_release_age.mjs) on every overridden version yourself before committing; do not trust--fixto have verified age.
After reviewing, run:
pnpm install4b. Manual override (when --fix is too noisy or wrong)
Write the entry directly in the overrides section of pnpm-workspace.yaml:
overrides:
vulnerable-package@<bad-range>: '^safe-version'Rules:
- Use the narrowest version specifier possible (e.g.
vulnerable-package@<1.2.3notvulnerable-package) - Use a bounded target specifier so future major versions cannot resolve accidentally:
- Prefer
^safe-versionfor normal semver packages when staying within the same major is safe - Use
>=safe-version <next-majorwhen the lower bound must be explicit - Use an exact version when compatibility is uncertain, the package is pre-1.0, or the package does not follow semver reliably
- Prefer
- Check existing overrides first — do not create duplicates
- Consolidate multiple overlapping ranges for the same package into one entry where safe
Key quoting rule: Wrap the key in single quotes whenever it starts with
@(scoped package) —@is not a valid YAML unquoted-scalar start token, so@babel/core@<7.29.6: ...raises a parse error. Simple keys and keys with spaces parse fine unquoted (quoting them is harmless):overrides: '@babel/core@<7.29.6': '^7.29.6' # scoped — key MUST be quoted js-yaml@<4.2.0: '^4.2.0' # simple — quoting optional qs@>=6.11.1 <=6.15.1: '>=6.15.2 <7' # spaces — also valid unquoted
Then run:
pnpm install4c. Lockfile handling
pnpm-lock.yaml is generated state. Do not hand-edit it as the primary fix. Change pnpm-workspace.yaml (catalogs/overrides) first, then let pnpm generate the lockfile:
pnpm installIf the install runs in a non-interactive or frozen-by-default environment, use the explicit lockfile update path:
CI=true pnpm install --no-frozen-lockfileTo verify the lockfile is canonical before committing, run:
CI=true pnpm install --lockfile-only --no-frozen-lockfile
CI=true pnpm install --frozen-lockfileIf you remove incidental lockfile noise by editing hunks, immediately rerun both commands above. If pnpm rewrites the hunk, keep pnpm's output. Only commit pnpm-lock.yaml when pnpm has generated or revalidated it.
5. Validate the Fix
Run all checks in order. Stop at the first failure and fix before continuing.
# 1. Vulnerability resolved
pnpm audit
# 2. No package / peer-dep conflicts. Do NOT pipe to grep — that swallows pnpm's
# exit code. strictPeerDependencies:true makes a real conflict hard-fail here.
CI=true pnpm install --lockfile-only --no-frozen-lockfile # confirm pnpm preserves/regenerates lockfile
CI=true pnpm install --frozen-lockfile # confirm the resulting lockfile is stable
# 3. Typecheck (tsc --noEmit)
pnpm typecheck
# 4. Tests (100% coverage enforced — a failure signals a breaking change from the patch)
pnpm test:coverage
# 5. Prettier formatting check
pnpm format:check
# 6. ESLint
pnpm lintUse the project's own scripts (
pnpm lint, notnpx eslint):npxmay fetch from the registry instead of using the installed binary. There is no build step in this workspace.
ESLint regressions after patching surface during pnpm lint. A common cause is that the patched package is used by ESLint itself (e.g. @eslint/eslintrc, ajv, @typescript-eslint/*, eslint-plugin-*). See references/eslint-update-notes.md for resolution patterns.
6. Commit (only when explicitly asked)
Do NOT commit unless the user explicitly requests it. Do NOT push or open a PR unless asked.
If the current branch is main, create a feature branch first:
git checkout -b fix/security-patch-<vulnerable-package>Then, when the user asks to commit:
git add pnpm-workspace.yaml pnpm-lock.yaml
git commit -m "fix: patch <vulnerable-package> vulnerability"Key Files in This Project
| File | Purpose |
pnpm-workspace.yaml | Catalog version ranges + overrides section |
pnpm-lock.yaml | Generated lockfile. Commit it after pnpm generates/revalidates it; do not hand-edit it as the primary fix |
package.json | Dep names only — values are catalog:dev. Do NOT edit versions here; all ranges live in the pnpm-workspace.yaml catalog |
Constraints
- Never use
pnpm addwithout--save-catalog-name dev— all deps use thedevcatalog - Do not add overrides if a parent minor/patch upgrade can resolve it
- Overrides block the normal resolution graph — each one is technical debt; justify it
- Always run
pnpm installafterpnpm audit --fix— the lockfile is not updated otherwise - Do not trust manual
pnpm-lock.yamledits — prove lockfile correctness withCI=true pnpm install --lockfile-only --no-frozen-lockfileandCI=true pnpm install --frozen-lockfile
Resources
scripts/check_release_age.mjs— verify a package version is older than 10,080 minutes using pnpm's configured registryreferences/eslint-update-notes.md— patterns for when patching breaks ESLint
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
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.

