/security-vuln-remediation
Remediate security vulnerabilities found by Grype or pnpm audit. Use when a security scan fails, a CVE needs fixing, or you need to analyze, upgrade, override, or ignore a vulnerable dependency.
$ npx -y skills add stacklok/toolhive-studio --skill security-vuln-remediation --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/security-vuln-remediation
Context preview
The summary Claude sees to decide when to auto-load this skill.
Remediate security vulnerabilities found by Grype or pnpm audit. Use when a security scan fails, a CVE needs fixing, or you need to analyze, upgrade, override, or ignore a vulnerable dependency.
SKILL.md
security-vuln-remediation.SKILL.mdname: security-vuln-remediation
description: Remediate security vulnerabilities found by Grype or pnpm audit. Use when a security scan fails, a CVE needs fixing, or you need to analyze, upgrade, override, or ignore a vulnerable dependency.
Security Vulnerability Remediation
Playbook for analyzing and remediating security vulnerabilities in this Electron/Node.js project. Applies to both CI (Cursor agent in GitHub Actions) and local development.
Project Context
- **Package manager**: pnpm 11 (lockfile: `pnpm-lock.yaml`)
- **Scanner**: Grype with config at `.grype.yaml` (only reports vulnerabilities with a fix available)
- **Audit**: `pnpm audit --prod --audit-level=moderate`
- **Existing overrides**: `overrides` block in `pnpm-workspace.yaml` — used to pin transitive dependencies to patched versions (pnpm 11 no longer reads the `pnpm` field from `package.json`)
- **Production deps**: listed under `dependencies` in `package.json`
- **Dev-only deps**: listed under `devDependencies` in `package.json` — not shipped to users
Remediation Workflow
Follow these steps in order. Stop at the first step that resolves the vulnerability.
Step 1 — Identify Vulnerabilities
Run both scanners and capture the output:
grype . --config .grype.yaml
pnpm audit --prod --audit-level=moderate
For each finding, record:
- CVE ID (e.g. `CVE-2024-12345`)
- Affected package and installed version
- Fixed version (if available)
- Severity (critical / high / medium)
- Whether the package is a direct or transitive dependency
Step 2 — Trace the Dependency
For each vulnerable package, understand who pulls it in:
pnpm why <package-name>
Record:
- Which direct dependency depends on it
- How many versions of the package are installed
- Whether it appears under `dependencies` (production) or `devDependencies` (dev-only)
Step 3 — Attempt an Upgrade
Check if a patch/minor upgrade of the **direct** dependency resolves the CVE:
pnpm update <direct-dependency>
Or, if the vulnerable package is a direct dependency itself, update its version range in `package.json`.
After the change:
1. Run `pnpm install` to regenerate the lockfile 2. Re-run `grype . --config .grype.yaml` to verify the vulnerability is gone
If the upgrade resolves it, this step is complete. Move to the next vulnerability.
Step 4 — Apply a pnpm Override
If no non-breaking upgrade is available, or the fix requires a major version bump of a transitive dependency that is safe to force:
Add or update an entry in the `overrides` block inside `pnpm-workspace.yaml`. You MUST follow the existing override style used in the project. Current overrides look like this:
overrides:
fast-xml-parser: '>=5.5.9'
lodash-es: '>=4.17.23'
tar: '>=7.5.7'
Rules for overrides (follow strictly):
1. **Always use the `>=` prefix for values** — this allows future patches. Example: `'>=1.2.3'`. 2. **BEFORE writing any override, check `pnpm why <package>` for multiple major versions.** This is mandatory. If the tree contains more than one major line, an unscoped override would force ALL consumers onto the overridden version, breaking packages that expect a different major. 3. **Use a simple top-level override ONLY when one major line exists** — if every installation of the package is on the same major, a single `package: '>=fixed'` entry is safe:
some-package: '>=1.2.3'
4. **Use parent-scoped overrides when multiple majors coexist** — scope the override to the dependency path that pulls in the vulnerable version using `'parent>package'` syntax:
'parent-pkg>vulnerable-pkg': '>=2.0.1'
This only overrides `vulnerable-pkg` when required by `parent-pkg`, leaving other consumers on their compatible major. Pick the nearest direct parent that exclusively uses the vulnerable major line.
**WRONG** — never use an unscoped override when multiple majors exist:
vulnerable-pkg: '>=2.0.1'
This would force every consumer onto v2, breaking those that depend on v1.
5. **Only override actually vulnerable versions** — if `pnpm why` shows multiple major lines but only one is in the advisory's vulnerable range, override only that version's path. Do not add overrides for versions that are not vulnerable. 6. **Three valid override-key forms** — pick the most surgical one that resolves the advisory: 1. `package: '>=fixed'` — top-level, only when a single major line exists in the tree (see Rule 3). 2. `'parent>package': '>=fixed'` — parent-scoped, when multiple majors coexist and a specific parent pulls in the vulnerable major (see Rule 4). 3. `'package@versionRange': fixedVersion` — version-range-keyed, when **multiple vulnerable major lines coexist** and each needs its own targeted bump regardless of importer. The range lives in the key; the value is a fixed target version (no `>=` prefix). Example from this repo (`pnpm-workspace.yaml`):
'brace-expansion@>=4.0.0 <5.0.5': 5.0.5
'brace-expansion@>=2.0.0 <2.0.3': 2.0.3
'brace-expansion@<1.1.13': 1.1.14Prefer this form over many parent-scoped entries when the advisory spans multiple majors. Avoid it when a single-major top-level (form 1) or one `parent>package` (form 2) would do — those are easier to read.
After the change:
1. Run `pnpm install` to regenerate the lockfile 2. Re-run `grype . --config .grype.yaml` to verify the vulnerability is gone
Step 5 — Add a Grype Ignore (Last Resort)
Only if ALL of the following are true:
- The upgrade/override did not resolve the issue or would break functionality
- The vulnerable package is **not** a production dependency (only in `devDependencies` tree)
- The vulnerability's attack vector does not apply to a desktop Electron app
Add an ignore entry to `.grype.yaml`:
ignore:
- vulnerability: CVE-XXXX-XXXXX
package:
name: <package-name>
type: npm
reason:Read more
name: security-vuln-remediation description: Remediate security vulnerabilities found by Grype or pnpm audit. Use when a security scan fails, a CVE needs fixing, or you need to analyze, upgrade, override, or ignore a vulnerable dependency.
Security Vulnerability Remediation
Playbook for analyzing and remediating security vulnerabilities in this Electron/Node.js project. Applies to both CI (Cursor agent in GitHub Actions) and local development.
Project Context
- **Package manager**: pnpm 11 (lockfile: `pnpm-lock.yaml`)
- **Scanner**: Grype with config at `.grype.yaml` (only reports vulnerabilities with a fix available)
- **Audit**: `pnpm audit --prod --audit-level=moderate`
- **Existing overrides**: `overrides` block in `pnpm-workspace.yaml` — used to pin transitive dependencies to patched versions (pnpm 11 no longer reads the `pnpm` field from `package.json`)
- **Production deps**: listed under `dependencies` in `package.json`
- **Dev-only deps**: listed under `devDependencies` in `package.json` — not shipped to users
Remediation Workflow
Follow these steps in order. Stop at the first step that resolves the vulnerability.
Step 1 — Identify Vulnerabilities
Run both scanners and capture the output:
grype . --config .grype.yaml pnpm audit --prod --audit-level=moderate
For each finding, record:
- CVE ID (e.g. `CVE-2024-12345`)
- Affected package and installed version
- Fixed version (if available)
- Severity (critical / high / medium)
- Whether the package is a direct or transitive dependency
Step 2 — Trace the Dependency
For each vulnerable package, understand who pulls it in:
pnpm why <package-name>
Record:
- Which direct dependency depends on it
- How many versions of the package are installed
- Whether it appears under `dependencies` (production) or `devDependencies` (dev-only)
Step 3 — Attempt an Upgrade
Check if a patch/minor upgrade of the **direct** dependency resolves the CVE:
pnpm update <direct-dependency>
Or, if the vulnerable package is a direct dependency itself, update its version range in `package.json`.
After the change:
1. Run `pnpm install` to regenerate the lockfile 2. Re-run `grype . --config .grype.yaml` to verify the vulnerability is gone
If the upgrade resolves it, this step is complete. Move to the next vulnerability.
Step 4 — Apply a pnpm Override
If no non-breaking upgrade is available, or the fix requires a major version bump of a transitive dependency that is safe to force:
Add or update an entry in the `overrides` block inside `pnpm-workspace.yaml`. You MUST follow the existing override style used in the project. Current overrides look like this:
overrides: fast-xml-parser: '>=5.5.9' lodash-es: '>=4.17.23' tar: '>=7.5.7'
Rules for overrides (follow strictly):
1. **Always use the `>=` prefix for values** — this allows future patches. Example: `'>=1.2.3'`. 2. **BEFORE writing any override, check `pnpm why <package>` for multiple major versions.** This is mandatory. If the tree contains more than one major line, an unscoped override would force ALL consumers onto the overridden version, breaking packages that expect a different major. 3. **Use a simple top-level override ONLY when one major line exists** — if every installation of the package is on the same major, a single `package: '>=fixed'` entry is safe:
some-package: '>=1.2.3'
4. **Use parent-scoped overrides when multiple majors coexist** — scope the override to the dependency path that pulls in the vulnerable version using `'parent>package'` syntax:
'parent-pkg>vulnerable-pkg': '>=2.0.1'
This only overrides `vulnerable-pkg` when required by `parent-pkg`, leaving other consumers on their compatible major. Pick the nearest direct parent that exclusively uses the vulnerable major line.
**WRONG** — never use an unscoped override when multiple majors exist:
vulnerable-pkg: '>=2.0.1'
This would force every consumer onto v2, breaking those that depend on v1.
5. **Only override actually vulnerable versions** — if `pnpm why` shows multiple major lines but only one is in the advisory's vulnerable range, override only that version's path. Do not add overrides for versions that are not vulnerable. 6. **Three valid override-key forms** — pick the most surgical one that resolves the advisory: 1. `package: '>=fixed'` — top-level, only when a single major line exists in the tree (see Rule 3). 2. `'parent>package': '>=fixed'` — parent-scoped, when multiple majors coexist and a specific parent pulls in the vulnerable major (see Rule 4). 3. `'package@versionRange': fixedVersion` — version-range-keyed, when **multiple vulnerable major lines coexist** and each needs its own targeted bump regardless of importer. The range lives in the key; the value is a fixed target version (no `>=` prefix). Example from this repo (`pnpm-workspace.yaml`):
'brace-expansion@>=4.0.0 <5.0.5': 5.0.5
'brace-expansion@>=2.0.0 <2.0.3': 2.0.3
'brace-expansion@<1.1.13': 1.1.14Prefer this form over many parent-scoped entries when the advisory spans multiple majors. Avoid it when a single-major top-level (form 1) or one `parent>package` (form 2) would do — those are easier to read.
After the change:
1. Run `pnpm install` to regenerate the lockfile 2. Re-run `grype . --config .grype.yaml` to verify the vulnerability is gone
Step 5 — Add a Grype Ignore (Last Resort)
Only if ALL of the following are true:
- The upgrade/override did not resolve the issue or would break functionality
- The vulnerable package is **not** a production dependency (only in `devDependencies` tree)
- The vulnerability's attack vector does not apply to a desktop Electron app
Add an ignore entry to `.grype.yaml`:
ignore:
- vulnerability: CVE-XXXX-XXXXX
package:
name: <package-name>
type: npm
reason:Run any Model Context Protocol (MCP) server — securely, instantly, anywhere. ToolHive is the easiest way to discover, deploy, and manage MCP servers. Launch any MCP server in a locked-down container with just a few clicks.
Repo: stacklok/toolhive-studio
Other skills on toolhive-studio.
- /bug-fix-tdd
Reproduce and fix bugs using TDD. Use when analyzing a bug report, writing a regression test, or applying a minimal fix. Covers test placement, mock patterns, and the red-green-refactor workflow for automated bug fixing.
Open skill - /deep-links
Deep links in ToolHive Studio. Use when implementing, debugging, or asking about deep link features (toolhive-gui:// protocol), adding new deep link intents, understanding the deep link architecture, IPC model, or platform/packaging support.
Open skill - /devcontainer-dev
Spin up and interact with ToolHive Studio's containerized dev environment (Xvfb + noVNC + DinD). Use when running, testing, or debugging the app in isolation — locally, in a git worktree, or in GitHub Codespaces; when touching `.devcontainer/*`, `scripts/devcontainer-*.sh`, or
Open skill - /skill-creator
Create new AI agent skills for Claude Code, Codex, and Cursor. Use when asked to create a skill, add a new agent capability, or set up a slash command.
Open skill - /skill-editor
REQUIRED for editing any skill file. Ensures changes sync to Claude, Codex, and Cursor. Never edit .claude/skills/ files directly - always use this skill.
Open skill - /testing-api-assertions
Verify API requests in tests. Use when testing that correct API calls are made for create, update, or delete operations. Use when testing mutations, form submissions, or actions with backend side effects.
Open skill

