skills/fix-vulnerabilities/SKILL.md
Fix multiple dependency vulnerabilities across multiple repos. Parses Vanta-style vulnerability entries, groups by repo, creates a single fix branch per repo, applies all fixes, verifies compatibility, and creates PRs after user approval. Use when the user says '/fix-vulnerabilities' or asks to fix vulnerabilities across repos.
npx skillsauth add soyio-id/skills fix-vulnerabilitiesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Resolve dependency vulnerabilities across multiple repositories from a batch of vulnerability entries.
The user provides one or more vulnerability entries, typically in Vanta format:
[Vanta] [github] [<repo-name>] npm-<package> <vulnerable-range>/<CVE-ID>
Examples:
[Vanta] [github] [soyio-rn-sdk] npm-minimatch < 3.1.3/CVE-2026-26996
[Vanta] [github] [soyio-docs] npm-minimatch >= 9.0.0, < 9.0.6/CVE-2026-26996
[Vanta] [github] [privacy-center] npm-minimatch >= 9.0.0, < 9.0.6/CVE-2026-26996
Some repos that Vanta reports have been consolidated into monorepos. When parsing, remap these repo names to their monorepo equivalent:
soyio-docs-bot-action → soyio-docs-bot (now lives in soyio-docs-bot/bot/)soyio-docs-indexer-action → soyio-docs-bot (now lives in soyio-docs-bot/indexer/)privacy-center → embeds (now lives in embeds/apps/privacy-center/)If aliases appear in the same batch, merge their vulnerabilities under the monorepo during the grouping phase and keep the affected app path for validation. For example, privacy-center findings should be grouped under embeds and validated with pnpm --filter privacy-center ... commands.
Entries like [Vanta] [aws] [aws] faraday:2.13.4/CVE-2026-25765 refer to gems detected in the production infrastructure. These should be treated as vulnerabilities in the soyio repo (check Gemfile / Gemfile.lock). The version shown (e.g., 2.13.4) is the currently installed version, NOT the fixed version. Ask the user for the fixed version before proceeding.
The input format may vary. Extract the following from each entry:
repo_name: the repository name (e.g., soyio-rn-sdk)package_name: the vulnerable package (e.g., minimatch), stripping the npm- or gem- prefixvulnerable_range: the range of vulnerable versions (e.g., >= 9.0.0, < 9.0.6)cve_id: the CVE identifier (e.g., CVE-2026-26996)package_manager: inferred from prefix (npm- → NODE, gem- → RUBY)The workspace root is the parent directory of this skill's location. Repos are sibling directories in the workspace root. Read the workspace instructions (AGENTS.md and, when present, CLAUDE.md) plus the target repo's local instructions to understand:
main, except soyio which uses master)privacy-center living in embeds/apps/privacy-centerBefore starting, present the full grouped plan to the user and wait for explicit approval before making any changes. If an EnterPlanMode tool is available, use it. Otherwise, present the plan as text output and ask the user to confirm before proceeding.
{ repo_dir, app_path?, vulnerabilities: [{ original_repo_name, package_name, vulnerable_range, cve_id, package_manager }] }embeds/apps/privacy-centerfix/vulnerabilities-<date> (e.g., fix/vulnerabilities-2026-03-23)fix/<package_name>-vulnerability insteadBefore starting, save the current working directory. All repo work must use absolute paths or cd into the repo and cd back. After completing ALL repos, return to the original working directory so the user's shell location is unchanged.
For each repo, in sequence:
cd <workspace_root>/<repo_dir>
git checkout <main_branch>
git pull
git checkout -b <branch_name>
privacy-center, perform git operations in the monorepo root (<workspace_root>/embeds) and keep track of the affected app path (apps/privacy-center). Do not modify the deprecated standalone privacy-center repo unless the user explicitly asks for it.Determine the package manager from workspace instructions or by checking for lockfiles in the resolved repo root:
yarn.lock → yarnpnpm-lock.yaml → pnpmpackage-lock.json → npmGemfile.lock → bundlerNODE:
package.json for a direct dependency. In a monorepo app, check the app manifest first (for example embeds/apps/privacy-center/package.json) and then note whether overrides/resolutions are managed at the repo root.why command to understand the dependency tree:
yarn why <package_name>pnpm why <package_name>npm explain <package_name>RUBY:
Gemfile for direct dependencyGemfile.lock for installed versionGemfile.lock to identify the parent gem or gems that introduce itNODE — Direct dependency:
package.json (dependencies or devDependencies) to the minimum fixed version (first version outside the vulnerable range)NODE — Transitive dependency (not a direct dependency):
yarn why, pnpm why, or npm explain after the direct dependency bump to verify whether the vulnerable transitive dependency is gone or now resolved to a fixed version.>= 9.0.0, < 9.0.6, resolve to ^9.0.6, NOT to ^10.x. If vulnerable range is < 3.1.3, resolve to ^3.1.3, NOT to ^9.x."resolutions" in package.json. NEVER use wildcard "**/package" when the same package exists across multiple major version lines (e.g., minimatch 3.x AND 9.x). Yarn 1 resolutions are path-based, not version-based — a wildcard like "**/minimatch": "^3.1.4" catches ALL ranges (including ^9.x) and forces them all to 3.x, silently downgrading consumers. Instead:
yarn why <package> to identify each consumer and its required major version"**/<consumer>/package": "^<fixed-for-that-major>"yarn install, verify in yarn.lock that each range resolves to its own major line (not grouped with another major)"pnpm.overrides" in package.json (e.g., "pnpm": { "overrides": { "<package>": "^<fixed>" } })"overrides" in package.jsonRUBY — Direct dependency:
Gemfilebundle update <package_name> --conservativeRUBY — Transitive dependency:
Gemfile.lock after the parent gem bump to verify whether the vulnerable transitive gem is gone or updated to a fixed version.bundle update <package_name> --conservative.Install commands by package manager:
yarn installpnpm installnpm installAfter applying ALL fixes for this repo:
Check resolved versions are correct:
yarn why <package_name>pnpm why <package_name>npm explain <package_name>grep '<package_name>' Gemfile.lockRun lint/build to ensure nothing breaks. Use the commands from workspace instructions for the specific repo or app. For privacy-center findings routed into embeds, validate with the privacy-center workspace commands such as pnpm --filter privacy-center lint, pnpm --filter privacy-center typecheck, and pnpm --filter privacy-center build.
If a check fails:
After completing each repo, report:
Do NOT commit or push yet. Leave the changes uncommitted so the user can review the diffs locally before proceeding.
Version bump for SDK repos: For soyio-rn-sdk and soy-io-widget, bump the version field in package.json (patch increment) as part of the fix. These are published packages, so the version must change for the fix to reach consumers.
Wait for the user to review the uncommitted changes and give explicit approval before committing, pushing, or creating PRs. This is critical — the user needs to inspect the diffs while they are still uncommitted.
For each repo, once approved:
package.json, app package.json, lockfile, Gemfile, Gemfile.lock, as applicable)fix(security): update <package> to <version> to fix <CVE>fix(security): update vulnerable dependencies (<package1>, <package2>, ...)git push -u origin <branch_name>
gh pr create:cd <workspace_root>/<repo_dir>
gh pr create --base <main_branch> --title "<title>" --body "$(cat <<'EOF'
<body>
EOF
)"
PR title format:
fix(security): update <package> to fix <CVE>fix(security): update vulnerable dependenciesPR body must be in Spanish and follow this structure:
### Contexto
- <Why this change exists — reference CVEs and severity>
### Que se esta haciendo
- <Bullet points summarizing each fix>
### Verificacion
- <Lint/build results>
- <Version verification results>
Return all PR URLs to the user.
rm pnpm-lock.yaml && pnpm install). Always run the install command incrementally so the lockfile is updated in place.cd back to the original working directory where the skill was invoked. The user's shell location must remain unchanged.tools
Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification
tools
Create or reuse a coordinated Soyio parity workspace across soyio, soyio-dashboard, and soyio-embeds, then start the matching local runtimes.
testing
Triage and prepare automated dependency security PRs for merge with minimal risk. Identify bot PRs that need intervention, resolve required issues only, refresh stale branches safely, detect superseded PRs, and keep diffs dependency-focused.
tools
Create an isolated worktree for a new branch, existing branch, or PR review. Prefer repo-local worktree commands when they exist, and fall back to vanilla git worktrees otherwise.