diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index fe8492c..353593f 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,29 +9,29 @@ }, "plugins": [ { - "name": "research-scan", - "source": "./skills/research-scan", + "name": "scan", + "source": "./skills/scan", "skills": "./", "description": "Run a full dependency scan using the Socket CLI. Creates a scan in the Socket dashboard, checks all dependencies for vulnerabilities and supply-chain risks, performs Tier 1 reachability analysis for enterprise customers, and provides license compliance auditing with SBOM generation." }, { - "name": "research-inspect", - "source": "./skills/research-inspect", + "name": "inspect", + "source": "./skills/inspect", "skills": "./", "description": "Research a package before you depend on it — pull every signal from Socket (scores, alerts, malware verdicts, CVEs, supply-chain risk), check the socket.dev package page, evaluate alternatives, and surface available Socket patches." }, - { - "name": "dep-patch", - "source": "./skills/dep-patch", - "skills": "./", - "description": "Apply Socket's binary-level security patches without changing dependency versions. Uses socket-patch apply to fix vulnerabilities in-place. For CI/CD and infrastructure setup, use the /setup skill." - }, { "name": "setup", "source": "./skills/setup", "skills": "./", "description": "Set up Socket — prompt for API key, install the CLI, authenticate, configure policies and tokens, set up CI/CD for firewall or patch modes across GitHub, GitLab, Bitbucket, and other systems." }, + { + "name": "dep-patch", + "source": "./skills/dep-patch", + "skills": "./", + "description": "Apply Socket's binary-level security patches without changing dependency versions. Uses socket-patch apply to fix vulnerabilities in-place. For CI/CD and infrastructure setup, use the /setup skill." + }, { "name": "dep-upgrade", "source": "./skills/dep-upgrade", @@ -45,8 +45,14 @@ "description": "Evaluate and remove a single unused dependency from your project. Searches the entire codebase for all usages (imports, requires, config refs, scripts, type packages, indirect usage), reports findings, and performs full removal with verification." }, { - "name": "repair", - "source": "./skills/repair", + "name": "dep-replace", + "source": "./skills/dep-replace", + "skills": "./", + "description": "Replace a dependency with an alternative package, eliminate it via code rewrite, or use socket-optimize for optimized replacements." + }, + { + "name": "fix", + "source": "./skills/fix", "skills": "./", "description": "Holistic dependency repair — orchestrates cleanup, patching, and upgrades in a single workflow with three aggressiveness levels (conservative, cautious, full)." } diff --git a/.opencode/skills b/.opencode/skills new file mode 120000 index 0000000..42c5394 --- /dev/null +++ b/.opencode/skills @@ -0,0 +1 @@ +../skills \ No newline at end of file diff --git a/README.md b/README.md index b9409e6..157aa11 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Socket Security Skills are definitions for dependency security tasks like vulner - **Claude Code** (Anthropic) — native skill/plugin support - **Codex** (OpenAI) — Agent Skills standard + AGENTS.md fallback - **Gemini CLI** (Google DeepMind) — extensions support +- **OpenCode** — skill directory support - **Cursor** — plugin manifest support - **VS Code Copilot / GitHub Copilot** — via AGENTS.md or Skills CLI - **Windsurf** — via Skills CLI @@ -101,6 +102,15 @@ For contributors, regenerate manifests with: ./scripts/publish.sh ``` +### OpenCode + +This repository includes an `.opencode/skills` directory that OpenCode discovers automatically. + +1. Clone or install this repo into your project +2. OpenCode will discover skills from `.opencode/skills/` + +Or manually copy skill folders into your project's `.opencode/skills/` directory. + ### Other Agents (VS Code Copilot, Windsurf, Roo Code, etc.) For any agent that supports the Agent Skills standard or custom instructions: @@ -131,14 +141,14 @@ Install, authenticate, and configure Socket for your project. |------|-------------|---------------| | `setup` | Set up Socket — prompt for API key, install the CLI, authenticate, configure policies and tokens, set up CI/CD for firewall or patch modes across GitHub, GitLab, Bitbucket, and other systems. | [SKILL.md](skills/setup/SKILL.md) | -#### Research +#### Analysis Scan dependencies and inspect individual packages for security risks. | Name | Description | Documentation | |------|-------------|---------------| -| `research-inspect` | Research a package before you depend on it — pull every signal from Socket (scores, alerts, malware verdicts, CVEs, supply-chain risk), check the socket.dev package page, evaluate alternatives, and surface available Socket patches. | [SKILL.md](skills/research-inspect/SKILL.md) | -| `research-scan` | Run a full dependency scan using the Socket CLI. Creates a scan in the Socket dashboard, checks all dependencies for vulnerabilities and supply-chain risks, performs Tier 1 reachability analysis for enterprise customers, and provides license compliance auditing with SBOM generation. | [SKILL.md](skills/research-scan/SKILL.md) | +| `inspect` | Research a package before you depend on it — pull every signal from Socket (scores, alerts, malware verdicts, CVEs, supply-chain risk), check the socket.dev package page, evaluate alternatives, and surface available Socket patches. | [SKILL.md](skills/inspect/SKILL.md) | +| `scan` | Run a full dependency scan using the Socket CLI. Creates a scan in the Socket dashboard, checks all dependencies for vulnerabilities and supply-chain risks, performs Tier 1 reachability analysis for enterprise customers, and provides license compliance auditing with SBOM generation. | [SKILL.md](skills/scan/SKILL.md) | #### Dependency Management @@ -148,15 +158,16 @@ Upgrade, patch, and clean up individual dependencies. |------|-------------|---------------| | `dep-cleanup` | Evaluate and remove a single unused dependency from your project. Searches the entire codebase for all usages (imports, requires, config refs, scripts, type packages, indirect usage), reports findings, and performs full removal with verification. | [SKILL.md](skills/dep-cleanup/SKILL.md) | | `dep-patch` | Apply Socket's binary-level security patches without changing dependency versions. Uses socket-patch apply to fix vulnerabilities in-place. For CI/CD and infrastructure setup, use the /setup skill. | [SKILL.md](skills/dep-patch/SKILL.md) | +| `dep-replace` | Replace a dependency with an alternative package, eliminate it via code rewrite, or use socket-optimize for optimized replacements. | [SKILL.md](skills/dep-replace/SKILL.md) | | `dep-upgrade` | Use socket fix to find and update vulnerable dependencies one at a time, then fix any breaking changes in the codebase. Security-audited upgrades with automated code migration. | [SKILL.md](skills/dep-upgrade/SKILL.md) | -#### Repair +#### Fix Holistic dependency repair — orchestrate cleanup, patching, and upgrades in a single phased workflow. | Name | Description | Documentation | |------|-------------|---------------| -| `repair` | Holistic dependency repair — orchestrates cleanup, patching, and upgrades in a single workflow with three aggressiveness levels (conservative, cautious, full). | [SKILL.md](skills/repair/SKILL.md) | +| `fix` | Holistic dependency repair — orchestrates cleanup, patching, and upgrades in a single workflow with three aggressiveness levels (conservative, cautious, full). | [SKILL.md](skills/fix/SKILL.md) | ## Contributing diff --git a/agents/AGENTS.md b/agents/AGENTS.md index 603ae12..047a2c0 100644 --- a/agents/AGENTS.md +++ b/agents/AGENTS.md @@ -8,10 +8,11 @@ You have additional SKILLs documented in directories containing a "SKILL.md" fil |-------|-------------| | dep-cleanup | Evaluate and remove a single unused dependency from your project. Searches the entire codebase for all usages (imports, requires, config refs, scripts, type packages, indirect usage), reports findings, and performs full removal with verification. | | dep-patch | Apply Socket's binary-level security patches without changing dependency versions. Uses socket-patch apply to fix vulnerabilities in-place. For CI/CD and infrastructure setup, use the /setup skill. | +| dep-replace | Replace a dependency with an alternative package, eliminate it via code rewrite, or use socket-optimize for optimized replacements. | | dep-upgrade | Use socket fix to find and update vulnerable dependencies, then fix any breaking changes in the codebase. Security-audited upgrades with automated code migration. | -| repair | Holistic dependency repair — orchestrates cleanup, patching, and upgrades in a single workflow with three aggressiveness levels (conservative, cautious, full). Delegates to /dep-cleanup, /dep-patch, and /dep-upgrade as subroutines. | -| research-inspect | Research a package before you depend on it — pull every signal from Socket (scores, alerts, malware verdicts, CVEs, supply-chain risk), check the socket.dev package page, evaluate alternatives, and surface available Socket patches. | -| research-scan | Run a full dependency scan using the Socket CLI. Creates a scan in the Socket dashboard, checks all dependencies for vulnerabilities and supply-chain risks, performs Tier 1 reachability analysis for enterprise customers, and provides license compliance auditing with SBOM generation. | +| fix | Holistic dependency repair — orchestrates cleanup, replacement, patching, and upgrades in a single workflow with three aggressiveness levels (conservative, cautious, full). Delegates to /dep-cleanup, /dep-replace, /dep-patch, and /dep-upgrade as subroutines. | +| inspect | Research a package before you depend on it — pull every signal from Socket (scores, alerts, malware verdicts, CVEs, supply-chain risk), check the socket.dev package page, evaluate alternatives, and surface available Socket patches. | +| scan | Run a full dependency scan using the Socket CLI. Creates a scan in the Socket dashboard, checks all dependencies for vulnerabilities and supply-chain risks, performs Tier 1 reachability analysis for enterprise customers, and provides license compliance auditing with SBOM generation. | | setup | Set up Socket — prompt for API key, install the CLI, authenticate, configure policies and tokens, set up CI/CD for firewall or patch modes across GitHub, GitLab, Bitbucket, and other systems. | ## Usage @@ -27,8 +28,9 @@ Paths referenced within SKILL folders are relative to that SKILL. For example th The skills are located in: - `skills/dep-cleanup/SKILL.md` - `skills/dep-patch/SKILL.md` +- `skills/dep-replace/SKILL.md` - `skills/dep-upgrade/SKILL.md` -- `skills/repair/SKILL.md` -- `skills/research-inspect/SKILL.md` -- `skills/research-scan/SKILL.md` +- `skills/fix/SKILL.md` +- `skills/inspect/SKILL.md` +- `skills/scan/SKILL.md` - `skills/setup/SKILL.md` diff --git a/scripts/generate-agents.ts b/scripts/generate-agents.ts index 4fa34f5..5b503f2 100644 --- a/scripts/generate-agents.ts +++ b/scripts/generate-agents.ts @@ -73,16 +73,16 @@ interface CategoryDef { const CATEGORIES: [string, CategoryDef][] = [ ["setup", { label: "Setup", description: "Install, authenticate, and configure Socket for your project." }], - ["research", { label: "Research", description: "Scan dependencies and inspect individual packages for security risks." }], + ["analysis", { label: "Analysis", description: "Scan dependencies and inspect individual packages for security risks." }], ["dep", { label: "Dependency Management", description: "Upgrade, patch, and clean up individual dependencies." }], - ["repair", { label: "Repair", description: "Holistic dependency repair — orchestrate cleanup, patching, and upgrades in a single phased workflow." }], + ["fix", { label: "Fix", description: "Holistic dependency repair — orchestrate cleanup, patching, and upgrades in a single phased workflow." }], ]; function getCategory(skillName: string): string { if (skillName === "setup") return "setup"; - if (skillName.startsWith("research-")) return "research"; + if (skillName === "scan" || skillName === "inspect") return "analysis"; if (skillName.startsWith("dep-")) return "dep"; - if (skillName === "repair") return "repair"; + if (skillName === "fix") return "fix"; return "setup"; } diff --git a/skills/dep-cleanup/SKILL.md b/skills/dep-cleanup/SKILL.md index 20ce33d..9ad7764 100644 --- a/skills/dep-cleanup/SKILL.md +++ b/skills/dep-cleanup/SKILL.md @@ -24,7 +24,7 @@ If the user specifies a package name, use that. Otherwise, ask which package the If the user isn't sure which package to evaluate, help them pick one: - Check `devDependencies` first — removing unused dev dependencies is lower risk - Look for packages with names that suggest narrow or outdated functionality -- Suggest running `/research-scan` first to get an overview of the dependency landscape +- Suggest running `/scan` first to get an overview of the dependency landscape **One package at a time.** If the user wants to evaluate multiple packages, run this workflow once per package sequentially. @@ -187,4 +187,4 @@ Follow the standard build & test verification workflow (see `skills/_shared/veri - Some packages are used only in CI, deployment scripts, or editor configs — the search in Step 3 covers these - For PyPI, consult the package metadata on pypi.org if the import name is unclear - For monorepos, check usage across all workspaces before removing a root dependency -- After cleanup, use the `/research-scan` skill to verify no issues remain in the dependency set +- After cleanup, use the `/scan` skill to verify no issues remain in the dependency set diff --git a/skills/dep-patch/SKILL.md b/skills/dep-patch/SKILL.md index af5fd2f..808d396 100644 --- a/skills/dep-patch/SKILL.md +++ b/skills/dep-patch/SKILL.md @@ -106,5 +106,5 @@ To keep patches applied automatically in CI/CD or via postinstall hooks, use the - Use `SocketDev/action@v1` (correct casing) in GitHub workflow files - For monorepos, use `patch-cwd` to target specific directories - Commit `.socket/manifest.json` to track which patches are applied -- After patching, use the `/research-scan` skill to verify no residual vulnerabilities remain +- After patching, use the `/scan` skill to verify no residual vulnerabilities remain - Combine with the `/dep-upgrade` skill for vulnerabilities that don't have binary patches available diff --git a/skills/dep-replace/SKILL.md b/skills/dep-replace/SKILL.md new file mode 100644 index 0000000..c343f66 --- /dev/null +++ b/skills/dep-replace/SKILL.md @@ -0,0 +1,287 @@ +--- +name: dep-replace +description: Replace a dependency with an alternative package, eliminate it via code + rewrite, or use socket-optimize for optimized replacements. +--- + +# Dep Replace + +Replace a dependency with an alternative package, eliminate it via code rewrite, or use `socket-optimize` for optimized replacements. This skill targets ONE specific package at a time — building a full usage map, presenting replacement strategies, and executing the migration with build and test verification. + +## When to Use + +- The user wants to swap a dependency for a different package (e.g., migrating from `moment` to `dayjs`) +- The user wants to replace a flagged or unmaintained dependency +- The user wants to inline a trivial utility package (e.g., `is-odd`, `left-pad`) +- The user wants to use `socket-optimize` to find optimized replacements +- The user asks how to migrate away from a specific package + +## Prerequisites + +- **Socket CLI** — optional but recommended. Required for Strategy A (`socket-optimize`). Install via `/setup` if not available. +- **Build and test commands** — the project should have a working build and test setup for verification. + +## Step 1: Identify the Target Package + +If the user specifies a package name, use that. If they also specify a replacement, note it for Step 5. + +If the user isn't sure which package to replace, help them pick one: +- Suggest running `/scan` first to identify flagged or low-score dependencies +- Check for packages with known maintenance issues or security alerts +- Look for trivial utility packages that could be inlined + +**One package at a time.** If the user wants to replace multiple packages, run this workflow once per package sequentially. + +## Step 2: Detect the Ecosystem + +Identify which ecosystem the target package belongs to by checking manifest and lock files: + +| Ecosystem | Manifest Files | +|-----------|---------------| +| npm | `package.json` + `package-lock.json` | +| pnpm | `package.json` + `pnpm-lock.yaml` | +| yarn | `package.json` + `yarn.lock` | +| PyPI | `requirements.txt`, `pyproject.toml`, `setup.py`, `setup.cfg`, `Pipfile` | +| Cargo | `Cargo.toml` | +| Bundler | `Gemfile` | +| Maven | `pom.xml` | +| NuGet | `*.csproj`, `packages.config` | +| Go | `go.mod` | + +For npm, pnpm, and yarn: differentiate by which lock file is present (`package-lock.json`, `pnpm-lock.yaml`, or `yarn.lock`). + +## Step 3: Search for All Usages + +Search the **entire codebase** for every reference to the target package. Be thorough — check all of the following: + +### Direct Import/Require Patterns + +| Ecosystem | Patterns to Search | +|-----------|-------------------| +| npm/pnpm/yarn | `require('pkg')`, `require("pkg")`, `import ... from 'pkg'`, `import ... from "pkg"`, `import 'pkg'`, `import "pkg"`, `import('pkg')`, `import("pkg")`. Also check for subpath imports like `pkg/sub`. | +| PyPI | `import pkg`, `from pkg import ...`. **Note:** the package name on PyPI often differs from the import name (e.g. `Pillow` → `PIL`, `beautifulsoup4` → `bs4`, `python-dotenv` → `dotenv`, `scikit-learn` → `sklearn`, `PyYAML` → `yaml`). Check both the package name and common import aliases. **Tip:** run `pip show ` — the output includes a `Location` field and the actual top-level package names are the directories at that location matching the package. Alternatively, check `top_level.txt` in the package's `.dist-info` directory. | +| Cargo | `use crate_name::`, `extern crate crate_name`, references in proc-macro attributes. **Note:** hyphens in crate names become underscores in Rust code (e.g. `serde-json` → `serde_json`). | +| Bundler | `require 'gem_name'`, `require "gem_name"`, autoload references. | +| Maven | `import groupId.artifactId.` or subpackage patterns in `.java` and `.kt` files. Match on the groupId prefix. | +| NuGet | `using Namespace;` and `using static Namespace.` in `.cs` files. Match on the package's root namespace. | +| Go | Import paths in `.go` files matching the module path from `go.mod` `require` entries. | + +### Indirect Usage Detection + +Some dependencies are used indirectly and will not appear in import statements. Check all of the following for the target package: + +- **`@types/*` packages** — corresponds to a base package (e.g. `@types/node` supports Node.js APIs); check if the base package is used +- **Babel/ESLint/Jest/Prettier plugins** — referenced by short name in config files (e.g. `eslint-plugin-react` is listed as `react` in `.eslintrc`); search config files for the short name +- **CLI tools in `scripts`** — packages that provide binaries referenced in `package.json` `scripts` (e.g. `rimraf`, `concurrently`, `cross-env`); check the `scripts` block +- **Peer dependencies** — required by other installed packages; check if any installed package lists it as a peer dependency +- **Build tools and bundler plugins** — `webpack`, `vite`, `rollup`, `esbuild`, `parcel`, `turbopack` and their plugins; check config files +- **PostCSS/Tailwind plugins** — referenced in `postcss.config.*` or `tailwind.config.*` +- **Python entry points and console scripts** — packages providing CLI commands configured in `pyproject.toml` or `setup.cfg` +- **Bundler groups** — gems in `:development` or `:test` groups may only be used in specific contexts +- **Cargo build dependencies** — crates in `[build-dependencies]` are used by `build.rs` +- **Maven plugins** — `` entries in `pom.xml` are not imported in code + +### Where to Search + +Search beyond just source code: +- Source files (`.ts`, `.js`, `.py`, `.rs`, `.go`, `.java`, `.cs`, `.rb`, etc.) +- Configuration files (`.eslintrc`, `babel.config.*`, `jest.config.*`, `webpack.config.*`, `vite.config.*`, etc.) +- `package.json` `scripts` block +- CI/CD configs (`.github/workflows/`, `.gitlab-ci.yml`, etc.) +- Shell scripts (`*.sh`) +- Dockerfiles +- Documentation that references the package as a runtime dependency + +### Build the Usage Map + +**This is what distinguishes dep-replace from dep-cleanup.** For each call site, record: +- The **file path and line number** +- The **specific APIs used** (named imports, method calls, constructor invocations) +- The **usage pattern** (e.g., "uses `merge` for deep object merging", "uses `format` for date formatting") + +This usage map drives the migration — it tells you exactly what API surface needs to be replaced. + +``` +Usage map for 'lodash': + + src/utils/helper.ts:14 — import { merge, cloneDeep } from 'lodash' + - merge (deep object merge, called with 2 args) + - cloneDeep (object cloning) + + src/api/handler.ts:3 — import { get, set } from 'lodash' + - get (nested property access with dot-path) + - set (nested property assignment with dot-path) + + src/components/Table.tsx:8 — import { sortBy, groupBy } from 'lodash' + - sortBy (array sorting by key) + - groupBy (array grouping by key) + +Unique APIs used: merge, cloneDeep, get, set, sortBy, groupBy (6 total) +``` + +## Step 4: Report Findings + +Present ALL findings to the user with the full usage map: + +``` +**{package-name}** — found {N} usages across {M} files + +Usage map: + {file}:{line} — {import statement} + - {api} ({usage pattern}) + ... + +Unique APIs used: {list} ({count} total) +``` + +If the package has zero usages, suggest using `/dep-cleanup` instead (it's unused, not needing replacement). + +## Step 5: Determine Replacement Strategy + +Present three strategies in priority order. If the user already specified a replacement package, skip to Strategy B with that package pre-selected. + +### Strategy A: `socket-optimize` + +If the Socket CLI is installed: + +1. Run `socket-optimize ` to get optimized replacement suggestions +2. Present the suggestions to the user with package names, descriptions, and Socket scores +3. If the user picks one, proceed to Step 6 with that replacement + +If the Socket CLI is not installed, mention that `socket-optimize` is available via `/setup` and move to Strategy B. + +### Strategy B: Research Alternatives via `/inspect` + +1. Research candidate replacement packages — use knowledge of the ecosystem to identify 2-4 alternatives +2. For each candidate, gather via `/inspect`: + - Socket score and alerts + - Number of dependencies + - Package size + - Maintenance status (last publish date, open issues) +3. Build an **API compatibility table** showing which APIs from the usage map each candidate supports: + +``` +API Compatibility: + +| API Used | dayjs | date-fns | luxon | +|-----------------|---------------|---------------|---------------| +| format() | .format() | format() | .toFormat() | +| parse() | dayjs() | parse() | DateTime.fromFormat() | +| diff() | .diff() | differenceIn*()| .diff() | +| add() | .add() | add*() | .plus() | +| isValid() | .isValid() | isValid() | .isValid | + +Coverage: dayjs 5/5, date-fns 5/5, luxon 5/5 +``` + +4. Present the comparison and let the user pick a replacement + +### Strategy C: Inline Elimination + +Suitable when ALL of the following are true: +- The package implements less than ~50 lines of logic +- The package has no or minimal transitive dependencies +- Only 1-3 APIs from the package are used in the codebase + +If the package qualifies: + +1. Propose an inline implementation for each used API +2. Show the user the proposed code +3. If approved, the inline code will be placed in a local utility file during Step 6 + +**Always ask user approval before proceeding with any strategy.** + +## Step 6: Execute the Migration + +### 6a. Install Replacement Package (Strategies A & B) + +| Ecosystem | Install Command | +|-----------|----------------| +| npm | `npm install {package}` | +| pnpm | `pnpm add {package}` | +| yarn | `yarn add {package}` | +| PyPI | `pip install {package}` or add to `requirements.txt` / `pyproject.toml` | +| Cargo | `cargo add {package}` | +| Bundler | Add to `Gemfile`, then `bundle install` | +| Maven | Add `` to `pom.xml`, then `mvn dependency:resolve` | +| NuGet | `dotnet add package {package}` | +| Go | `go get {package}` | + +For Strategy C (inline), skip this step. + +### 6b. Rewrite Import Statements + +- **Strategies A & B**: Update all import/require statements to use the new package name and its API surface +- **Strategy C**: Replace imports with a reference to the new local utility file (e.g., `import { isOdd } from './utils/is-odd'`) + +For Strategy C, create the local utility file with the inline implementation. + +### 6c. Rewrite API Call Sites + +Using the usage map from Step 3, rewrite each call site: + +- **Rename APIs** if the replacement uses different names (e.g., `moment.format()` → `dayjs.format()`) +- **Adjust signatures** if the replacement has different parameter orders or types +- **Handle behavioral differences** — note any cases where the replacement behaves differently and add comments or adapter code + +### 6d. Remove Original Package + +| Ecosystem | Removal Command | +|-----------|----------------| +| npm | `npm uninstall {package}` | +| pnpm | `pnpm remove {package}` | +| yarn | `yarn remove {package}` | +| PyPI | Edit `requirements.txt` / `pyproject.toml` directly to remove the line, then `pip install -r requirements.txt` or `poetry lock` | +| Cargo | `cargo remove {package}` | +| Bundler | Edit `Gemfile` to remove the entry, then `bundle install` | +| Maven | Edit `pom.xml` to remove the `` block, then `mvn dependency:resolve` | +| NuGet | `dotnet remove package {package}` | +| Go | Edit `go.mod` to remove the entry, then `go mod tidy` | + +### 6e. Handle `@types/*` Packages + +- Remove `@types/{old-package}` if it exists in devDependencies +- Install `@types/{new-package}` if the replacement needs it and it exists + +### 6f. Clean Up Config References + +Update any configuration files that reference the old package: +- ESLint/Babel/Jest/Prettier plugin lists +- Build tool config (webpack loaders, Vite plugins, etc.) +- `package.json` scripts that use the package's CLI +- PostCSS/Tailwind plugin lists + +## Step 7: Verify + +Follow the standard build & test verification workflow (see `skills/_shared/verify-build.md`): + +1. **Build the project** using its standard build command +2. **Run the test suite** to catch any issues with the replacement +3. **Search for leftover references** to the old package name across the codebase +4. If something fails, **revert all changes** — restore the original package, revert code changes, and report the failure to the user + +## Error Handling + +- **Build or tests fail after migration**: Check error messages to identify whether the issue is a missing API, a behavioral difference, or a type mismatch. Revert all changes and report the specific incompatibility. +- **No suitable replacement found**: Report that no alternative meets the criteria. Suggest the user check Socket's package page for more options or consider whether the dependency is truly needed. +- **Replacement package has worse Socket score**: Warn the user that the replacement may introduce new risks. Let them decide whether to proceed. +- **Partial API coverage**: If no single replacement covers all used APIs, report the gap and let the user decide — they may want to use multiple packages or inline the uncovered APIs. +- **`socket-optimize` not available**: Fall back to Strategy B (manual research). + +## How This Differs from /dep-cleanup + +| Aspect | /dep-cleanup | /dep-replace | +|--------|-------------|-------------| +| **Goal** | Remove an unused dependency | Swap a used dependency for an alternative | +| **Precondition** | Package is (suspected) unused | Package IS used but needs replacement | +| **Usage search** | Determines IF the package is used | Builds a detailed map of WHAT APIs are used | +| **Code changes** | Remove dead imports and code | Rewrite imports and call sites to use the replacement | +| **Outcome** | Fewer dependencies | Same or fewer dependencies, different package | + +## Tips + +- For large migrations (many call sites or complex API differences), use subagents to parallelize the rewrite across files +- Run `/scan` after replacement to verify the new dependency's security posture +- When replacing a package used across many files, consider creating a thin adapter module first, then swapping the implementation behind it +- For Strategy C (inline), keep the utility file small and well-tested — don't inline complex logic +- If the user isn't sure which replacement to pick, Strategy B's API compatibility table helps make an informed decision diff --git a/skills/dep-upgrade/SKILL.md b/skills/dep-upgrade/SKILL.md index 53ed4f9..7b5da2c 100644 --- a/skills/dep-upgrade/SKILL.md +++ b/skills/dep-upgrade/SKILL.md @@ -129,7 +129,7 @@ Iterate until everything passes: 1. **Build the project** to check for compile/type errors 2. **Run the full test suite** and fix any failing tests -3. **Run the `/research-scan` skill** to confirm no new vulnerabilities were introduced by the upgrades +3. **Run the `/scan` skill** to confirm no new vulnerabilities were introduced by the upgrades 4. **Re-run `socket fix --all --no-apply-fixes --json`** to verify no fixable vulnerabilities remain If tests fail after fixing, investigate each failure: @@ -149,7 +149,7 @@ Fixing all vulnerabilities in a Node.js project (success case): - Major bump applied → 2 test failures in route tests - Fix route handler code to match new Express API - Tests pass → commit → reports success -6. All subagents succeeded → run `/research-scan` skill → no new vulnerabilities +6. All subagents succeeded → run `/scan` skill → no new vulnerabilities Failure case — main agent stops on first failure: @@ -204,6 +204,6 @@ Use `/dep-upgrade` when you want full version upgrades. Use `/dep-patch` when yo - **Stop on failure** — if any single update cannot be completed, halt the entire process and report to the user rather than continuing with a broken state - Commit after each successful update so progress is saved and failures can be cleanly reverted - Use `--minimum-release-age 2d` to avoid upgrading to freshly-published versions -- Combine with the `/research-inspect` skill to compare security profiles before and after upgrades -- After all fixes are applied, run the `/research-scan` skill to verify no new risks were introduced +- Combine with the `/inspect` skill to compare security profiles before and after upgrades +- After all fixes are applied, run the `/scan` skill to verify no new risks were introduced - For monorepos, use `--include` and `--exclude` to target specific workspaces diff --git a/skills/repair/SKILL.md b/skills/fix/SKILL.md similarity index 86% rename from skills/repair/SKILL.md rename to skills/fix/SKILL.md index cb2c8a2..ae8e07e 100644 --- a/skills/repair/SKILL.md +++ b/skills/fix/SKILL.md @@ -1,13 +1,14 @@ --- -name: repair -description: Holistic dependency repair — orchestrates cleanup, patching, and upgrades - in a single workflow with three aggressiveness levels (conservative, cautious, full). - Delegates to /dep-cleanup, /dep-patch, and /dep-upgrade as subroutines. +name: fix +description: Holistic dependency repair — orchestrates cleanup, replacement, patching, + and upgrades in a single workflow with three aggressiveness levels (conservative, + cautious, full). Delegates to /dep-cleanup, /dep-replace, /dep-patch, and /dep-upgrade + as subroutines. --- -# Repair +# Fix -Holistic dependency repair — orchestrate `/dep-cleanup`, `/dep-patch`, and `/dep-upgrade` into a single phased workflow. Choose from three aggressiveness levels (conservative, cautious, full) to control how far the repair goes. +Holistic dependency repair — orchestrate `/dep-cleanup`, `/dep-replace`, `/dep-patch`, and `/dep-upgrade` into a single phased workflow. Choose from three aggressiveness levels (conservative, cautious, full) to control how far the repair goes. This skill is an **orchestrator**. It does not have its own tools — it delegates every concrete action to the dep-* skills. @@ -97,8 +98,9 @@ Execute Phase 1a (unused dep removal) and Phase 1b (binary patches) as described After Level 1 completes, identify the single highest-value change that carries some risk. Prioritize in this order: 1. **Critical/high CVE upgrade** — a dependency with a known critical or high severity vulnerability that requires a version bump (use `socket fix --all --no-apply-fixes --json` to discover) -2. **Ambiguous unused dependency** — a package that is *probably* unused but was excluded from Phase 1a due to ambiguity (e.g., a `@types/*` package whose base package is not used, or a build plugin that may no longer be needed) -3. **Safe minor version bump** — a dependency with a minor/patch update available that fixes a medium-severity issue +2. **Replacement of a flagged dependency** — a dependency with a low Socket score or known maintenance issues that should be swapped for a better alternative (use `/dep-replace`) +3. **Ambiguous unused dependency** — a package that is *probably* unused but was excluded from Phase 1a due to ambiguity (e.g., a `@types/*` package whose base package is not used, or a build plugin that may no longer be needed) +4. **Safe minor version bump** — a dependency with a minor/patch update available that fixes a medium-severity issue Present the proposed change to the user with full context: @@ -142,6 +144,13 @@ Aggressive repair. Apply everything possible, skip and continue on individual fa 4. **Revert removals that break the build** — if removing a package causes failures, re-add it and mark it as "still needed" 5. Commit after each successful removal +### Phase 3b2: Replace Flagged Dependencies + +1. Review scan results for dependencies with low Socket scores, unmaintained status, or known supply-chain risks +2. For each flagged dependency, run `/dep-replace` to find and execute a replacement +3. **Skip and continue on failure** — if a replacement cannot be completed (no suitable alternative, migration too complex, tests fail), log it and move on +4. Commit after each successful replacement + ### Phase 3c: Patch Everything Remaining 1. Run `socket-patch apply` on everything remaining @@ -161,7 +170,7 @@ Aggressive repair. Apply everything possible, skip and continue on individual fa After all phases complete (regardless of level): -1. Run `/research-scan` to get a fresh security scan +1. Run `/scan` to get a fresh security scan 2. Compare findings against the pre-repair state 3. Report a summary: @@ -196,6 +205,6 @@ Repair Complete (Level 2 — Cautious) - Level 3 is best for major cleanup efforts where you're prepared to review and test extensively - Each level builds on the previous one, so you can start conservative and escalate - All changes are committed individually, making it easy to revert any single change -- Run `/research-scan` before and after repair to measure improvement +- Run `/scan` before and after repair to measure improvement - For monorepos, consider running repair on each workspace individually - Combine with `/setup` to ensure the Socket CLI is properly configured before starting diff --git a/skills/research-inspect/SKILL.md b/skills/inspect/SKILL.md similarity index 99% rename from skills/research-inspect/SKILL.md rename to skills/inspect/SKILL.md index 61c12e2..cd5c1d2 100644 --- a/skills/research-inspect/SKILL.md +++ b/skills/inspect/SKILL.md @@ -1,5 +1,5 @@ --- -name: research-inspect +name: inspect description: Research a package before you depend on it — pull every signal from Socket (scores, alerts, malware verdicts, CVEs, supply-chain risk), check the socket.dev package page, evaluate alternatives, and surface available Socket patches. --- @@ -217,7 +217,7 @@ A clear, actionable recommendation: safe to use, use with caution (with reasons) - Single-maintainer packages carry higher supply-chain risk - Large transitive dependency trees increase attack surface - If a package is flagged as malware, do NOT install it — recommend immediate removal if already present -- Use inspect results to inform decisions with the `/dep-upgrade`, `/dep-patch`, and `/research-scan` skills +- Use inspect results to inform decisions with the `/dep-upgrade`, `/dep-patch`, and `/scan` skills - Weigh Socket score and maintenance health over download count alone - Re-review periodically — a package's security posture changes over time - Prefer Socket patches over manual version pinning when available diff --git a/skills/research-scan/SKILL.md b/skills/scan/SKILL.md similarity index 97% rename from skills/research-scan/SKILL.md rename to skills/scan/SKILL.md index 76a5b4b..7d0e215 100644 --- a/skills/research-scan/SKILL.md +++ b/skills/scan/SKILL.md @@ -1,5 +1,5 @@ --- -name: research-scan +name: scan description: Run a full dependency scan using the Socket CLI. Creates a scan in the Socket dashboard, checks all dependencies for vulnerabilities and supply-chain risks, performs Tier 1 reachability analysis for enterprise customers, and provides license @@ -130,7 +130,7 @@ Reachability analysis generates a `.socket.facts.json` file in the project root Based on scan results, cross-reference other skills to resolve issues: - **Vulnerabilities with available fixes** — use the `/dep-upgrade` skill to apply safe upgrades -- **Packages needing deeper investigation** — use the `/research-inspect` skill to research specific packages +- **Packages needing deeper investigation** — use the `/inspect` skill to research specific packages - **Packages with Socket patches available** — use the `/dep-patch` skill to apply security patches - **Unused dependencies** — use the `/dep-cleanup` skill to remove packages that are no longer needed @@ -265,7 +265,7 @@ Produce a human-readable compliance summary: - Always run a scan after adding, updating, or removing dependencies to verify the project's security posture - Use `--json` for machine-readable output that is easier to parse and summarize -- Combine with the `/research-inspect` skill for deep-dives into specific flagged packages +- Combine with the `/inspect` skill for deep-dives into specific flagged packages - Combine with the `/dep-upgrade` skill to fix vulnerabilities discovered during the scan - Enterprise customers should use reachability analysis to prioritize fixes — focus on `reachable` vulnerabilities first - Scan results are available in the Socket dashboard for team visibility and historical tracking @@ -274,4 +274,4 @@ Produce a human-readable compliance summary: - For enterprise compliance, generate SBOMs in both CycloneDX and SPDX formats - Re-audit after adding or updating dependencies — license information can change between versions - When flagging GPL dependencies, check if they are dev-only — GPL in devDependencies is generally lower risk for commercial projects -- Use the `/research-inspect` skill to deep-dive into specific packages flagged during the audit +- Use the `/inspect` skill to deep-dive into specific packages flagged during the audit diff --git a/skills/setup/SKILL.md b/skills/setup/SKILL.md index ec654e9..b473da2 100644 --- a/skills/setup/SKILL.md +++ b/skills/setup/SKILL.md @@ -343,6 +343,6 @@ If the project uses an unusual build system: - `socket-patch apply` does not require an API key. - Use `SocketDev/action@v1` (correct casing) in GitHub workflow files. - For monorepos, use `patch-cwd` to target specific directories. -- After setup, use the `/research-scan` skill for a first audit and the `/research-inspect` skill for package inspection. +- After setup, use the `/scan` skill for a first audit and the `/inspect` skill for package inspection. - For GitHub repos, consider also installing the Socket Security GitHub App for automatic PR scanning. diff --git a/tests/tier1-structural/skill-discovery.test.ts b/tests/tier1-structural/skill-discovery.test.ts index e3166b1..e1e1e0e 100644 --- a/tests/tier1-structural/skill-discovery.test.ts +++ b/tests/tier1-structural/skill-discovery.test.ts @@ -6,7 +6,7 @@ import { parseFrontmatter } from "../../scripts/lib/frontmatter"; const ROOT = path.resolve(__dirname, "../.."); const SKILLS_DIR = path.join(ROOT, "skills"); -const EXPECTED_SKILLS = ["dep-cleanup", "dep-patch", "dep-upgrade", "repair", "research-inspect", "research-scan", "setup"]; +const EXPECTED_SKILLS = ["dep-cleanup", "dep-patch", "dep-replace", "dep-upgrade", "fix", "inspect", "scan", "setup"]; function getSkillDirs(): string[] { return fs diff --git a/tests/tier3-e2e/dep-replace.e2e.test.ts b/tests/tier3-e2e/dep-replace.e2e.test.ts new file mode 100644 index 0000000..4a30608 --- /dev/null +++ b/tests/tier3-e2e/dep-replace.e2e.test.ts @@ -0,0 +1,61 @@ +import { describe, it, beforeAll, afterAll, beforeEach } from "vitest"; +import { getAdapter, type AgentAdapter } from "../helpers/agent-adapters/index.js"; +import { copyFixture, cleanupTestRepo, buildSkillPrompt } from "../helpers/test-repos.js"; +import { expectScoreAboveThreshold } from "../helpers/assertions.js"; + +describe("Dep Replace E2E", () => { + let adapter: AgentAdapter; + let testDir: string; + + beforeAll(async () => { + adapter = getAdapter(); + const available = await adapter.isAvailable(); + if (!available) { + throw new Error( + `Agent '${adapter.name}' is not available. Install it or set TEST_AGENT to a different agent.` + ); + } + }); + + beforeEach(() => { + testDir = copyFixture("test-project"); + }); + + afterAll(() => { + if (testDir) cleanupTestRepo(testDir); + }); + + it("identifies replacement strategies for a dependency", { timeout: 300_000 }, async () => { + const response = await adapter.runPrompt({ + prompt: buildSkillPrompt( + "dep-replace", + "Analyze the 'is-odd' package in this project and suggest replacement strategies. Do not execute any migration, just present the strategies." + ), + workingDir: testDir, + timeoutMs: 240_000, + }); + + expectScoreAboveThreshold( + response, + ["is-odd", "strateg", "replace", "inline"], + 0.4 + ); + }); + + it("builds a usage map for a target dependency", { timeout: 300_000 }, async () => { + const response = await adapter.runPrompt({ + prompt: buildSkillPrompt( + "dep-replace", + "Build a usage map for the 'lodash' package in this project. List all files, line numbers, and specific APIs used. Do not execute any replacement." + ), + workingDir: testDir, + timeoutMs: 240_000, + }); + + expectScoreAboveThreshold( + response, + ["lodash", "usage", "import"], + 0.4 + ); + }); +}); diff --git a/tests/tier3-e2e/repair.e2e.test.ts b/tests/tier3-e2e/fix.e2e.test.ts similarity index 96% rename from tests/tier3-e2e/repair.e2e.test.ts rename to tests/tier3-e2e/fix.e2e.test.ts index 439f228..e2254a5 100644 --- a/tests/tier3-e2e/repair.e2e.test.ts +++ b/tests/tier3-e2e/fix.e2e.test.ts @@ -3,7 +3,7 @@ import { getAdapter, type AgentAdapter } from "../helpers/agent-adapters/index.j import { copyFixture, cleanupTestRepo, buildSkillPrompt } from "../helpers/test-repos.js"; import { expectScoreAboveThreshold } from "../helpers/assertions.js"; -describe("Repair E2E", () => { +describe("Fix E2E", () => { let adapter: AgentAdapter; let testDir: string; @@ -28,7 +28,7 @@ describe("Repair E2E", () => { it("identifies repair levels and environment", { timeout: 300_000 }, async () => { const response = await adapter.runPrompt({ prompt: buildSkillPrompt( - "repair", + "fix", "Analyze this project and describe what each repair level (conservative, cautious, full) would do. Detect the ecosystem and list the dependencies. Do not make any changes." ), workingDir: testDir, @@ -45,7 +45,7 @@ describe("Repair E2E", () => { it("performs conservative repair analysis", { timeout: 300_000 }, async () => { const response = await adapter.runPrompt({ prompt: buildSkillPrompt( - "repair", + "fix", "Run a conservative (Level 1) repair analysis on this project. Identify which dependencies appear unused and which patches are available. Do not actually remove or patch anything — just report what you would do." ), workingDir: testDir, @@ -62,7 +62,7 @@ describe("Repair E2E", () => { it("proposes a risky change for level 2", { timeout: 300_000 }, async () => { const response = await adapter.runPrompt({ prompt: buildSkillPrompt( - "repair", + "fix", "If this project were at repair Level 2 (cautious), what single risky change would you propose? Look at the dependencies for known vulnerabilities and suggest the highest-value upgrade. Do not apply it." ), workingDir: testDir, diff --git a/tests/tier3-e2e/research-inspect.e2e.test.ts b/tests/tier3-e2e/inspect.e2e.test.ts similarity index 95% rename from tests/tier3-e2e/research-inspect.e2e.test.ts rename to tests/tier3-e2e/inspect.e2e.test.ts index b708101..67a25ad 100644 --- a/tests/tier3-e2e/research-inspect.e2e.test.ts +++ b/tests/tier3-e2e/inspect.e2e.test.ts @@ -7,7 +7,7 @@ import { expectNoHallucinatedTools, } from "../helpers/assertions.js"; -describe("Research Inspect E2E", () => { +describe("Inspect E2E", () => { let adapter: AgentAdapter; beforeAll(async () => { @@ -23,7 +23,7 @@ describe("Research Inspect E2E", () => { it("reviews lodash and provides security info", { timeout: 300_000 }, async () => { const response = await adapter.runPrompt({ prompt: buildSkillPrompt( - "research-inspect", + "inspect", "Review the npm package 'lodash'. Try using `npx socket npm/lodash` to look up its Socket score. If the CLI command fails, still provide a review based on what you know about lodash's security posture, known vulnerabilities (especially in versions before 4.17.21), and maintenance status." ), workingDir: process.cwd(), @@ -40,7 +40,7 @@ describe("Research Inspect E2E", () => { it("reviews express and assesses health", { timeout: 300_000 }, async () => { const response = await adapter.runPrompt({ prompt: buildSkillPrompt( - "research-inspect", + "inspect", "Review the npm package 'express'. Try using `npx socket npm/express` to look up its Socket score. If the CLI command fails, still provide a review based on what you know about express's security posture, quality, and dependency footprint." ), workingDir: process.cwd(), diff --git a/tests/tier3-e2e/research-scan.e2e.test.ts b/tests/tier3-e2e/scan.e2e.test.ts similarity index 95% rename from tests/tier3-e2e/research-scan.e2e.test.ts rename to tests/tier3-e2e/scan.e2e.test.ts index 7569918..0f092b8 100644 --- a/tests/tier3-e2e/research-scan.e2e.test.ts +++ b/tests/tier3-e2e/scan.e2e.test.ts @@ -6,7 +6,7 @@ import { expectScoreAboveThreshold, } from "../helpers/assertions.js"; -describe("Research Scan E2E", () => { +describe("Scan E2E", () => { let adapter: AgentAdapter; let testDir: string; @@ -31,7 +31,7 @@ describe("Research Scan E2E", () => { it("scans project and reports findings", { timeout: 300_000 }, async () => { const response = await adapter.runPrompt({ prompt: buildSkillPrompt( - "research-scan", + "scan", "Scan this project's dependencies for security risks. Use the Socket CLI to create a scan and report the findings." ), workingDir: testDir, @@ -48,7 +48,7 @@ describe("Research Scan E2E", () => { it("identifies specific vulnerable package", { timeout: 300_000 }, async () => { const response = await adapter.runPrompt({ prompt: buildSkillPrompt( - "research-scan", + "scan", "Use the Socket CLI to check if any dependencies have known CVEs or vulnerabilities." ), workingDir: testDir, @@ -66,7 +66,7 @@ describe("Research Scan E2E", () => { it("generates a compliance report", { timeout: 300_000 }, async () => { const response = await adapter.runPrompt({ prompt: buildSkillPrompt( - "research-scan", + "scan", "Audit the licenses of all dependencies in this project. Read the package.json and classify each dependency's license. Produce a compliance summary showing license types and any issues." ), workingDir: testDir, @@ -83,7 +83,7 @@ describe("Research Scan E2E", () => { it("identifies SBOM output format", { timeout: 300_000 }, async () => { const response = await adapter.runPrompt({ prompt: buildSkillPrompt( - "research-scan", + "scan", "What SBOM formats can you generate for this project? List the dependencies and describe how you would produce a CycloneDX or SPDX SBOM." ), workingDir: testDir,