Skip to content

Commit a235410

Browse files
docs: consolidate global CLI options + document OpenVEX generation (#93)
Move the flags that clap flattens into every subcommand into a single "Global Options" section (with env vars and precedence), and trim each command's table down to its command-specific flags. Also fixes a few stale entries (no `-d` short for `--dry-run`, repair's download-mode default is `diff` not `file`) and documents the previously-undocumented `--all-releases`, `--proxy-url`, `--lock-timeout`, `--break-lock`, `--debug`, and `--no-telemetry` flags. Adds a `vex` command entry and an "OpenVEX attestations" section covering product auto-detection, output channels, and how to feed the document into Grype/Trivy/vexctl. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 36d440e commit a235410

1 file changed

Lines changed: 121 additions & 76 deletions

File tree

README.md

Lines changed: 121 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,38 @@ socket-patch 550e8400-e29b-41d4-a716-446655440000
7878
# equivalent to: socket-patch get 550e8400-e29b-41d4-a716-446655440000
7979
```
8080

81+
## Global Options
82+
83+
These flags are accepted by **every** subcommand — they are flattened into each command's argument set, so `socket-patch <command> --json --cwd ./app` works uniformly. A command silently ignores any global flag it doesn't use (e.g. `list --global` parses fine and the flag is a no-op).
84+
85+
Each flag has a matching `SOCKET_*` environment variable. **Precedence is CLI arg > env var > default**, so a flag on the command line always wins over the environment.
86+
87+
| Flag | Env var | Description |
88+
|------|---------|-------------|
89+
| `--cwd <dir>` | `SOCKET_CWD` | Working directory (default: `.`). The manifest path is resolved relative to this. |
90+
| `-m, --manifest-path <path>` | `SOCKET_MANIFEST_PATH` | Path to the patch manifest, resolved relative to `--cwd` (default: `.socket/manifest.json`). |
91+
| `--api-url <url>` | `SOCKET_API_URL` | Socket API URL for the authenticated endpoint (default: `https://api.socket.dev`). |
92+
| `--api-token <token>` | `SOCKET_API_TOKEN` | Socket API token. When omitted, the public patch proxy is used. |
93+
| `-o, --org <slug>` | `SOCKET_ORG_SLUG` | Organization slug. Auto-resolved when omitted and a token is set. |
94+
| `--proxy-url <url>` | `SOCKET_PROXY_URL` | Public proxy URL used when no API token is set. |
95+
| `-e, --ecosystems <list>` | `SOCKET_ECOSYSTEMS` | Restrict to specific ecosystems (comma-separated, e.g. `npm,pypi`). |
96+
| `--download-mode <mode>` | `SOCKET_DOWNLOAD_MODE` | Artifact to fetch when local files are missing: `diff` (default, smallest delta), `package` (full per-package tarball), or `file` (legacy per-file blobs). |
97+
| `--offline` | `SOCKET_OFFLINE` | Strict airgap: never contact the network. Operations that need remote data fail loudly. |
98+
| `-g, --global` | `SOCKET_GLOBAL` | Operate on globally-installed packages. |
99+
| `--global-prefix <path>` | `SOCKET_GLOBAL_PREFIX` | Override the path used to discover globally-installed packages. |
100+
| `-j, --json` | `SOCKET_JSON` | Emit machine-readable JSON output. Every JSON response includes a `"status"` field (`"success"`, `"error"`, `"no_manifest"`, etc.) for reliable programmatic consumption. |
101+
| `-v, --verbose` | `SOCKET_VERBOSE` | Show extra detail in human-readable output. |
102+
| `-s, --silent` | `SOCKET_SILENT` | Suppress non-error output. |
103+
| `--dry-run` | `SOCKET_DRY_RUN` | Preview the operation without making any mutations. |
104+
| `-y, --yes` | `SOCKET_YES` | Skip interactive confirmation prompts. |
105+
| `--lock-timeout <secs>` | `SOCKET_LOCK_TIMEOUT` | Seconds to wait for `.socket/apply.lock` before giving up. `0`/unset = a single non-blocking try; a positive value retries with backoff. Only meaningful for mutating commands (`apply`, `rollback`, `repair`, `remove`). |
106+
| `--break-lock` | `SOCKET_BREAK_LOCK` | Force-remove a stale `.socket/apply.lock` before acquiring it. Use only when no other socket-patch process is running; emits an auditable `lock_broken` event in the JSON envelope. |
107+
| `--debug` | `SOCKET_DEBUG` | Emit verbose debug logs to stderr. |
108+
| `--no-telemetry` | `SOCKET_TELEMETRY_DISABLED` | Disable anonymous usage telemetry. |
109+
81110
## Commands
82111

83-
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.
112+
The tables below list only the **command-specific** flags. Every command also accepts the [Global Options](#global-options) above.
84113

85114
### `get`
86115

@@ -93,23 +122,18 @@ Alias: `download`
93122
socket-patch get <identifier> [options]
94123
```
95124

96-
**Options:**
125+
**Command-specific options** (plus all [Global Options](#global-options)):
97126
| Flag | Description |
98127
|------|-------------|
99-
| `--org <slug>` | Organization slug (required when using `SOCKET_API_TOKEN`) |
100128
| `--id` | Force identifier to be treated as a UUID |
101129
| `--cve` | Force identifier to be treated as a CVE ID |
102130
| `--ghsa` | Force identifier to be treated as a GHSA ID |
103131
| `-p, --package` | Force identifier to be treated as a package name |
104-
| `-y, --yes` | Skip confirmation prompt for multiple patches |
105132
| `--save-only` | Download patch without applying it (alias: `--no-apply`) |
106-
| `--one-off` | Apply patch immediately without saving to `.socket` folder |
107-
| `-g, --global` | Apply to globally installed packages |
108-
| `--global-prefix <path>` | Custom path to global `node_modules` |
109-
| `--json` | Output results as JSON |
110-
| `--api-token <token>` | Socket API token (overrides `SOCKET_API_TOKEN`) |
111-
| `--api-url <url>` | Socket API URL (overrides `SOCKET_API_URL`) |
112-
| `--cwd <dir>` | Working directory (default: `.`) |
133+
| `--one-off` | Apply patch immediately without saving to the `.socket` folder |
134+
| `--all-releases` | Download patches for every release/distribution variant of a matched package (PyPI wheel/sdist, RubyGems platform, Maven classifier), not just the installed one |
135+
136+
> Authenticated lookups require an org: pass `--org <slug>` (or set `SOCKET_ORG_SLUG`) when using `SOCKET_API_TOKEN`.
113137
114138
**Examples:**
115139
```bash
@@ -144,24 +168,16 @@ Scan installed packages for available security patches. Since v3.0 `scan --sync`
144168
socket-patch scan [options]
145169
```
146170

147-
**Options:**
171+
**Command-specific options** (plus all [Global Options](#global-options)):
148172
| Flag | Description |
149173
|------|-------------|
150174
| `--apply` | Download and apply selected patches in JSON mode (non-interactive). Without it, `scan --json` is read-only. |
151175
| `--prune` | Garbage-collect after the scan: remove manifest entries for uninstalled packages and orphan blob/diff/package-archive files. Off by default. |
152176
| `--sync` | Sugar for `--apply --prune`. The canonical bot-mode flag. |
153-
| `-d, --dry-run` | Preview what `--apply`/`--prune`/`--sync` would do without mutating disk. |
154-
| `--org <slug>` | Organization slug |
155-
| `--json` | Output results as JSON |
156-
| `-y, --yes` | Skip confirmation prompts |
157-
| `--ecosystems <list>` | Restrict to specific ecosystems (comma-separated, e.g. `npm,pypi`) |
158-
| `-g, --global` | Scan globally installed packages |
159-
| `--global-prefix <path>` | Custom path to global `node_modules` |
160177
| `--batch-size <n>` | Packages per API request (default: `100`) |
161-
| `--download-mode <mode>` | `diff` (default), `package`, or `file` |
162-
| `--api-token <token>` | Socket API token (overrides `SOCKET_API_TOKEN`) |
163-
| `--api-url <url>` | Socket API URL (overrides `SOCKET_API_URL`) |
164-
| `--cwd <dir>` | Working directory (default: `.`) |
178+
| `--all-releases` | Store patches for every release/distribution variant, not just the installed one — makes the manifest portable across environments (e.g. cross-platform CI caches) |
179+
180+
> Use `--dry-run` to preview what `--apply`/`--prune`/`--sync` would do without mutating disk.
165181
166182
**Examples:**
167183
```bash
@@ -199,20 +215,10 @@ Apply security patches from the local manifest.
199215
socket-patch apply [options]
200216
```
201217

202-
**Options:**
218+
**Command-specific options** (plus all [Global Options](#global-options)):
203219
| Flag | Description |
204220
|------|-------------|
205-
| `-d, --dry-run` | Verify patches without modifying files |
206-
| `-s, --silent` | Only output errors |
207221
| `-f, --force` | Skip pre-application hash verification (apply even if package version differs) |
208-
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
209-
| `--offline` | Do not download missing blobs; fail if any are missing |
210-
| `-g, --global` | Apply to globally installed packages |
211-
| `--global-prefix <path>` | Custom path to global `node_modules` |
212-
| `--ecosystems <list>` | Restrict to specific ecosystems (comma-separated, e.g. `npm,pypi`) |
213-
| `--json` | Output results as JSON |
214-
| `-v, --verbose` | Show detailed per-file verification information |
215-
| `--cwd <dir>` | Working directory (default: `.`) |
216222

217223
**Examples:**
218224
```bash
@@ -241,23 +247,10 @@ Rollback patches to restore original files. If no identifier is given, all patch
241247
socket-patch rollback [identifier] [options]
242248
```
243249

244-
**Options:**
250+
**Command-specific options** (plus all [Global Options](#global-options)):
245251
| Flag | Description |
246252
|------|-------------|
247-
| `-d, --dry-run` | Verify rollback without modifying files |
248-
| `-s, --silent` | Only output errors |
249-
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
250-
| `--offline` | Do not download missing blobs; fail if any are missing |
251-
| `-g, --global` | Rollback globally installed packages |
252-
| `--global-prefix <path>` | Custom path to global `node_modules` |
253-
| `--one-off` | Rollback by fetching original files from API (no manifest required) |
254-
| `--ecosystems <list>` | Restrict to specific ecosystems (comma-separated) |
255-
| `--json` | Output results as JSON |
256-
| `-v, --verbose` | Show detailed per-file verification information |
257-
| `--org <slug>` | Organization slug |
258-
| `--api-token <token>` | Socket API token (overrides `SOCKET_API_TOKEN`) |
259-
| `--api-url <url>` | Socket API URL (overrides `SOCKET_API_URL`) |
260-
| `--cwd <dir>` | Working directory (default: `.`) |
253+
| `--one-off` | Rollback by fetching original (`beforeHash`) files from the API — no manifest required |
261254

262255
**Examples:**
263256
```bash
@@ -286,12 +279,7 @@ List all patches in the local manifest.
286279
socket-patch list [options]
287280
```
288281

289-
**Options:**
290-
| Flag | Description |
291-
|------|-------------|
292-
| `--json` | Output as JSON |
293-
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
294-
| `--cwd <dir>` | Working directory (default: `.`) |
282+
No command-specific options — see [Global Options](#global-options) (`--json`, `--manifest-path`, `--cwd` are the relevant ones).
295283

296284
**Examples:**
297285
```bash
@@ -330,15 +318,10 @@ socket-patch remove <identifier> [options]
330318
**Arguments:**
331319
- `identifier` - Package PURL (e.g., `pkg:npm/package@version`) or patch UUID
332320

333-
**Options:**
321+
**Command-specific options** (plus all [Global Options](#global-options)):
334322
| Flag | Description |
335323
|------|-------------|
336324
| `--skip-rollback` | Only update manifest, do not restore original files |
337-
| `-g, --global` | Remove from globally installed packages |
338-
| `--global-prefix <path>` | Custom path to global `node_modules` |
339-
| `--json` | Output results as JSON |
340-
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
341-
| `--cwd <dir>` | Working directory (default: `.`) |
342325

343326
**Examples:**
344327
```bash
@@ -368,16 +351,10 @@ Alias: `gc`
368351
socket-patch repair [options]
369352
```
370353

371-
**Options:**
354+
**Command-specific options** (plus all [Global Options](#global-options)):
372355
| Flag | Description |
373356
|------|-------------|
374-
| `-d, --dry-run` | Show what would be done without doing it |
375-
| `--offline` | Skip network operations (cleanup only) |
376-
| `--download-only` | Only download missing blobs, do not clean up |
377-
| `--json` | Output results as JSON |
378-
| `-m, --manifest-path <path>` | Path to manifest (default: `.socket/manifest.json`) |
379-
| `--cwd <dir>` | Working directory (default: `.`) |
380-
| `--download-mode <mode>` | `file` (default), `diff`, or `package` |
357+
| `--download-only` | Only download missing artifacts, do not clean up (incompatible with `--offline`) |
381358

382359
**Examples:**
383360
```bash
@@ -403,13 +380,7 @@ Configure `package.json` postinstall scripts to automatically apply patches afte
403380
socket-patch setup [options]
404381
```
405382

406-
**Options:**
407-
| Flag | Description |
408-
|------|-------------|
409-
| `-d, --dry-run` | Preview changes without modifying files |
410-
| `-y, --yes` | Skip confirmation prompt |
411-
| `--json` | Output results as JSON |
412-
| `--cwd <dir>` | Working directory (default: `.`) |
383+
No command-specific options — see [Global Options](#global-options) (`--dry-run`, `--yes`, `--json`, `--cwd` are the relevant ones).
413384

414385
**Examples:**
415386
```bash
@@ -426,6 +397,78 @@ socket-patch setup --dry-run
426397
socket-patch setup --json -y
427398
```
428399

400+
### `vex`
401+
402+
Generate an [OpenVEX](https://github.com/openvex) 0.2.0 attestation describing the vulnerabilities that the applied patches have mitigated. See [OpenVEX attestations](#openvex-attestations) below for the full workflow.
403+
404+
**Usage:**
405+
```bash
406+
socket-patch vex [options]
407+
```
408+
409+
**Command-specific options** (plus all [Global Options](#global-options)):
410+
| Flag | Description |
411+
|------|-------------|
412+
| `-O, --output <path>` | Write the VEX document to this path instead of stdout. Required when combined with `--json`. (env: `SOCKET_VEX_OUTPUT`) |
413+
| `--product <id>` | Override the auto-detected top-level product PURL/identifier. (env: `SOCKET_VEX_PRODUCT`) |
414+
| `--no-verify` | Skip the on-disk file-hash check and trust the manifest — useful on a build machine that doesn't have the patched files laid out. (env: `SOCKET_VEX_NO_VERIFY`) |
415+
| `--doc-id <id>` | Override the document `@id`. Default is a random `urn:uuid:<v4>` regenerated each run; pin this for a reproducible identifier. (env: `SOCKET_VEX_DOC_ID`) |
416+
| `--compact` | Emit compact JSON instead of pretty-printed. (env: `SOCKET_VEX_COMPACT`) |
417+
418+
**Examples:**
419+
```bash
420+
# Print a VEX document to stdout (human-readable status goes to stderr)
421+
socket-patch vex
422+
423+
# Write the document to a file
424+
socket-patch vex --output socket.vex.json
425+
426+
# CI shape: VEX doc to file, machine-readable envelope to stdout
427+
socket-patch vex --json --output socket.vex.json
428+
429+
# Generate on a build box without verifying on-disk files
430+
socket-patch vex --no-verify --output socket.vex.json
431+
```
432+
433+
## OpenVEX attestations
434+
435+
`socket-patch vex` turns your local manifest into a signed-off statement of *which known vulnerabilities no longer affect your build* because a Socket patch has been applied. This lets vulnerability scanners stop flagging CVEs that you've already remediated in place — without bumping the package version.
436+
437+
**How it works**
438+
439+
1. Reads `.socket/manifest.json` and, unless `--no-verify` is passed, re-checks each patched file's hash on disk so the attestation only covers patches that are actually applied.
440+
2. Auto-detects the top-level **product** identifier (override with `--product`), probing in order:
441+
- `.git/config` `[remote "origin"]``pkg:github/<owner>/<repo>` (similar for GitLab/Bitbucket; raw URL otherwise)
442+
- `package.json``pkg:npm/<name>@<version>`
443+
- `pyproject.toml``pkg:pypi/<name>@<version>`
444+
- `Cargo.toml``pkg:cargo/<name>@<version>`
445+
3. Emits an OpenVEX 0.2.0 document whose statements mark each mitigated vulnerability as `not_affected` (justification: the patch is present), suitable for piping into `vexctl`, Grype, Trivy, and similar tools.
446+
447+
**Output channels**
448+
449+
| Invocation | VEX document | stdout |
450+
|------------|--------------|--------|
451+
| _default_ (no `--output`, no `--json`) | stdout | human-readable status on stderr |
452+
| `--output <path>` | the file | one-line summary |
453+
| `--json --output <path>` | the file | machine-readable envelope (the CI shape) |
454+
455+
`--json` requires `--output`, since the VEX document is itself JSON and would otherwise collide with the envelope on stdout.
456+
457+
**Using it with a scanner**
458+
459+
```bash
460+
# Generate the attestation as part of CI, then hand it to a scanner
461+
socket-patch vex --output socket.vex.json
462+
463+
# Suppress already-patched findings in Grype
464+
grype <image-or-dir> --vex socket.vex.json
465+
466+
# Or with Trivy
467+
trivy image --vex socket.vex.json <image>
468+
```
469+
470+
Run `socket-patch get` or `socket-patch scan --sync` first — `vex` errors with `no_patches` against an empty manifest.
471+
429472
## Scripting & CI/CD
430473

431474
All commands support `--json` for machine-readable output. JSON responses always include a `"status"` field for easy error detection:
@@ -452,6 +495,8 @@ When stdin is not a TTY (e.g., in CI pipelines), interactive prompts auto-procee
452495

453496
## Environment Variables
454497

498+
Every [Global Option](#global-options) has a matching `SOCKET_*` environment variable (listed in that table), and `vex`-specific flags map to `SOCKET_VEX_*`. The most commonly used variables are:
499+
455500
| Variable | Description |
456501
|----------|-------------|
457502
| `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. |

0 commit comments

Comments
 (0)