# Socket Patch CLI
Apply security patches to npm and Python dependencies without waiting for upstream fixes.
## Installation
### One-line install (recommended)
```bash
Detects your platform (macOS/Linux, x64/ARM64), downloads the latest binary, and installs to `/usr/local/bin` or `~/.local/bin`. Use `sudo sh` instead of `sh` if `/usr/local/bin` requires root.
<details>
<summary>Manual download</summary>
Download a prebuilt binary from the [latest release](https://github.com/SocketDev/socket-patch/releases/latest):
```bash
# macOS (Apple Silicon)
# macOS (Intel)
curl -fsSL https://github.com/SocketDev/socket-patch/releases/latest/download/socket-patch-x86_64-apple-darwin.tar.gz | tar xz
# Linux (x86_64)
curl -fsSL https://github.com/SocketDev/socket-patch/releases/latest/download/socket-patch-x86_64-unknown-linux-musl.tar.gz | tar xz
# Linux (ARM64)
Then move the binary onto your `PATH`:
```bash
sudo mv socket-patch /usr/local/bin/
```
</details>
### npm
```bash
npx @socketsecurity/socket-patch
```
Or install globally:
```bash
npm install -g @socketsecurity/socket-patch
```
### pip
```bash
pip install socket-patch
```
### Cargo
```bash
cargo install socket-patch-cli
```
By default this builds with npm and PyPI support. For additional ecosystems:
```bash
cargo install socket-patch-cli --features cargo,golang,maven,composer,nuget
```
## Quick Start
You can pass a patch UUID directly to `socket-patch` as a shortcut:
```bash
socket-patch 550e8400-e29b-41d4-a716-446655440000
# equivalent to: socket-patch get 550e8400-e29b-41d4-a716-446655440000
```
## Commands
All commands support `--json` for structured JSON output and `--cwd <dir>` to set the working directory (default: `.`). Every JSON response includes a `"status"` field (`"success"`, `"error"`, `"no_manifest"`, etc.) for reliable programmatic consumption.
### `get`
Get security patches from Socket API and apply them. Accepts a UUID, CVE ID, GHSA ID, PURL, or package name. The identifier type is auto-detected but can be forced with a flag.
Alias: `download`
**Usage:**
```bash
socket-patch get <identifier> [options]
```
**Options:**
| `--org <slug>` | Organization slug (required when using `SOCKET_API_TOKEN`) |
| `--id` | Force identifier to be treated as a UUID |
| `--cve` | Force identifier to be treated as a CVE ID |
| `--ghsa` | Force identifier to be treated as a GHSA ID |
| `-p, --package` | Force identifier to be treated as a package name |
| `-y, --yes` | Skip confirmation prompt for multiple patches |
| `--save-only` | Download patch without applying it (alias: `--no-apply`) |
| `--one-off` | Apply patch immediately without saving to `.socket` folder |
| `-g, --global` | Apply to globally installed packages |
| `--global-prefix <path>` | Custom path to global `node_modules` |
| `--json` | Output results as JSON |
| `--api-token <token>` | Socket API token (overrides `SOCKET_API_TOKEN`) |
| `--api-url <url>` | Socket API URL (overrides `SOCKET_API_URL`) |
| `--cwd <dir>` | Working directory (default: `.`) |
**Examples:**
```bash
# Get patch by UUID
socket-patch get 550e8400-e29b-41d4-a716-446655440000
# Get patch by CVE
socket-patch get CVE-2024-12345
# Get patch by GHSA
socket-patch get GHSA-xxxx-yyyy-zzzz
# Get patch by package name (fuzzy matches installed packages)
socket-patch get lodash
# Download only, don't apply
socket-patch get CVE-2024-12345 --save-only
# Apply to global packages
socket-patch get lodash -g
# JSON output for scripting
socket-patch get CVE-2024-12345 --json -y
```
### `scan`
Scan installed packages for available security patches. Since v3.0 `scan --sync` is the single command bots need for full auto-update: it discovers patches, applies them, and garbage-collects orphan blob files plus manifest entries for uninstalled packages — all in one invocation.
**Usage:**
```bash
socket-patch scan [options]
```
**Options:**
| `--apply` | Download and apply selected patches in JSON mode (non-interactive). Without it, `scan --json` is read-only. |
| `--prune` | Garbage-collect after the scan: remove manifest entries for uninstalled packages and orphan blob/diff/package-archive files. Off by default. |
| `--sync` | Sugar for `--apply --prune`. The canonical bot-mode flag. |
| `-d, --dry-run` | Preview what `--apply`/`--prune`/`--sync` would do without mutating disk. |
| `--org <slug>` | Organization slug |
| `--json` | Output results as JSON |
| `-y, --yes` | Skip confirmation prompts |
| `--ecosystems <list>` | Restrict to specific ecosystems (comma-separated, e.g. `npm,pypi`) |
| `-g, --global` | Scan globally installed packages |
| `--global-prefix <path>` | Custom path to global `node_modules` |
| `--batch-size <n>` | Packages per API request (default: `100`) |
| `--download-mode <mode>` | `diff` (default), `package`, or `file` |
| `--api-token <token>` | Socket API token (overrides `SOCKET_API_TOKEN`) |
| `--api-url <url>` | Socket API URL (overrides `SOCKET_API_URL`) |
| `--cwd <dir>` | Working directory (default: `.`) |
**Examples:**
```bash
# Scan local project (interactive prompt to apply)
socket-patch scan
# Scan with JSON output (discover + updates, no mutation)
socket-patch scan --json
# Bot mode: discover, apply, prune, sweep — all in one
socket-patch scan --json --sync --yes
# Apply without pruning manifest entries (default)
socket-patch scan --apply --yes
# Apply + prune explicitly (equivalent to --sync)
socket-patch scan --json --apply --prune --yes
# Preview a full sync without mutating disk
socket-patch scan --json --sync --yes --dry-run
# Scan only npm packages
socket-patch scan --ecosystems npm
# Scan global packages
socket-patch scan -g
```
### `apply`
Apply security patches from the local manifest.
**Usage:**
```bash
socket-patch apply [options]
```
**Options:**
| `-d, --dry-run` | Verify patches without modifying files |
| `-s, --silent` | Only output errors |
| `-f, --force` | Skip pre-application hash verification (apply even if package version differs) |
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
| `--offline` | Do not download missing blobs; fail if any are missing |
| `-g, --global` | Apply to globally installed packages |
| `--global-prefix <path>` | Custom path to global `node_modules` |
| `--ecosystems <list>` | Restrict to specific ecosystems (comma-separated, e.g. `npm,pypi`) |
| `--json` | Output results as JSON |
| `-v, --verbose` | Show detailed per-file verification information |
| `--cwd <dir>` | Working directory (default: `.`) |
**Examples:**
```bash
# Apply patches
socket-patch apply
# Dry run
socket-patch apply --dry-run
# Apply only npm patches
socket-patch apply --ecosystems npm
# Apply in offline mode
socket-patch apply --offline
# JSON output for CI/CD
socket-patch apply --json
```
### `rollback`
Rollback patches to restore original files. If no identifier is given, all patches are rolled back.
**Usage:**
```bash
socket-patch rollback [identifier] [options]
```
**Options:**
| `-d, --dry-run` | Verify rollback without modifying files |
| `-s, --silent` | Only output errors |
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
| `--offline` | Do not download missing blobs; fail if any are missing |
| `-g, --global` | Rollback globally installed packages |
| `--global-prefix <path>` | Custom path to global `node_modules` |
| `--one-off` | Rollback by fetching original files from API (no manifest required) |
| `--ecosystems <list>` | Restrict to specific ecosystems (comma-separated) |
| `--json` | Output results as JSON |
| `-v, --verbose` | Show detailed per-file verification information |
| `--org <slug>` | Organization slug |
| `--api-token <token>` | Socket API token (overrides `SOCKET_API_TOKEN`) |
| `--api-url <url>` | Socket API URL (overrides `SOCKET_API_URL`) |
| `--cwd <dir>` | Working directory (default: `.`) |
**Examples:**
```bash
# Rollback all patches
socket-patch rollback
# Rollback a specific package
socket-patch rollback "pkg:npm/lodash@4.17.20"
# Rollback by UUID
socket-patch rollback 550e8400-e29b-41d4-a716-446655440000
# Dry run
socket-patch rollback --dry-run
# JSON output
socket-patch rollback --json
```
### `list`
List all patches in the local manifest.
**Usage:**
```bash
socket-patch list [options]
```
**Options:**
| `--json` | Output as JSON |
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
| `--cwd <dir>` | Working directory (default: `.`) |
**Examples:**
```bash
# List patches
socket-patch list
# JSON output
socket-patch list --json
```
**Sample Output:**
```
Found 2 patch(es):
Package: pkg:npm/lodash@4.17.20
UUID: 550e8400-e29b-41d4-a716-446655440000
Tier: free
License: MIT
Vulnerabilities (1):
- GHSA-xxxx-yyyy-zzzz (CVE-2024-12345)
Severity: high
Summary: Prototype pollution in lodash
Files patched (1):
- lodash.js
```
### `remove`
Remove a patch from the manifest (rolls back files first by default).
**Usage:**
```bash
socket-patch remove <identifier> [options]
```
**Arguments:**
- `identifier` - Package PURL (e.g., `pkg:npm/package@version`) or patch UUID
**Options:**
| `--skip-rollback` | Only update manifest, do not restore original files |
| `-g, --global` | Remove from globally installed packages |
| `--global-prefix <path>` | Custom path to global `node_modules` |
| `--json` | Output results as JSON |
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
| `--cwd <dir>` | Working directory (default: `.`) |
**Examples:**
```bash
# Remove by PURL
socket-patch remove "pkg:npm/lodash@4.17.20"
# Remove by UUID
socket-patch remove 550e8400-e29b-41d4-a716-446655440000
# Remove without rolling back files
socket-patch remove "pkg:npm/lodash@4.17.20" --skip-rollback
# JSON output
socket-patch remove "pkg:npm/lodash@4.17.20" --json
```
### `repair`
Download missing blobs and clean up unused blobs.
Alias: `gc`
`repair` cleans up the `.socket/` directory without running a scan — useful when you've manually adjusted the manifest, recovered from a partial-failure state, or just want to free space. For the combined workflow (discover + apply + GC in one pass), use `scan --sync --json --yes` instead.
**Usage:**
```bash
socket-patch repair [options]
```
**Options:**
| `-d, --dry-run` | Show what would be done without doing it |
| `--offline` | Skip network operations (cleanup only) |
| `--download-only` | Only download missing blobs, do not clean up |
| `--json` | Output results as JSON |
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
| `--cwd <dir>` | Working directory (default: `.`) |
| `--download-mode <mode>` | `file` (default), `diff`, or `package` |
**Examples:**
```bash
# Full repair (download missing + clean up unused)
socket-patch repair
# Cleanup only, no downloads
socket-patch repair --offline
# Download missing blobs only
socket-patch repair --download-only
# JSON output for scripting
socket-patch repair --json
```
### `setup`
Configure `package.json` postinstall scripts to automatically apply patches after `npm install`.
**Usage:**
```bash
socket-patch setup [options]
```
**Options:**
| `-d, --dry-run` | Preview changes without modifying files |
| `-y, --yes` | Skip confirmation prompt |
| `--json` | Output results as JSON |
| `--cwd <dir>` | Working directory (default: `.`) |
**Examples:**
```bash
# Interactive setup
socket-patch setup
# Non-interactive
socket-patch setup -y
# Preview changes
socket-patch setup --dry-run
# JSON output for scripting
socket-patch setup --json -y
```
## Scripting & CI/CD
All commands support `--json` for machine-readable output. JSON responses always include a `"status"` field for easy error detection:
```bash
# Check for available patches in CI (read-only)
result=$(socket-patch scan --json --ecosystems npm)
# Auto-update bot mode: discover, apply, prune, sweep in one pass
pruned: .gc.prunedManifestEntries,
bytes_freed: .gc.bytesFreed
}'
# Pipe this into peter-evans/create-pull-request to open a PR with the changes.
# Apply patches and check result
```
When stdin is not a TTY (e.g., in CI pipelines), interactive prompts auto-proceed instead of blocking. Progress indicators and ANSI colors are automatically suppressed when output is piped.
## Environment Variables
| `SOCKET_API_TOKEN` | API authentication token. Use the raw token (`sktsec_<...>_api`) shown when it was generated, **not** the SHA-512 hash (`sha512-...`) that the dashboard may also display for identification. |
| `SOCKET_ORG_SLUG` | Default organization slug |
| `SOCKET_API_URL` | API base URL (default: `https://api.socket.dev`) |
## Manifest Format
Downloaded patches are stored in `.socket/manifest.json`:
```json
{
"patches": {
"pkg:npm/package-name@1.0.0": {
"uuid": "unique-patch-id",
"exportedAt": "2024-01-01T00:00:00Z",
"files": {
"path/to/file.js": {
"beforeHash": "git-sha256-before",
"afterHash": "git-sha256-after"
}
},
"vulnerabilities": {
"GHSA-xxxx-xxxx-xxxx": {
"cves": ["CVE-2024-12345"],
"summary": "Vulnerability summary",
"severity": "high",
"description": "Detailed description"
}
},
"description": "Patch description",
"license": "MIT",
"tier": "free"
}
}
}
```
Patched file contents are in `.socket/blob/` (named by git SHA256 hash).
## Supported Platforms
| macOS | ARM64 (Apple Silicon), x86_64 (Intel) |
| Linux | x86_64, ARM64, ARMv7, i686 |
| Windows | x86_64, ARM64, i686 |
| Android | ARM64 |