You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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>
# equivalent to: socket-patch get 550e8400-e29b-41d4-a716-446655440000
79
79
```
80
80
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. |
|`--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. |
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.
84
113
85
114
### `get`
86
115
@@ -93,23 +122,18 @@ Alias: `download`
93
122
socket-patch get <identifier> [options]
94
123
```
95
124
96
-
**Options:**
125
+
**Command-specific options** (plus all [Global Options](#global-options)):
97
126
| Flag | Description |
98
127
|------|-------------|
99
-
|`--org <slug>`| Organization slug (required when using `SOCKET_API_TOKEN`) |
100
128
|`--id`| Force identifier to be treated as a UUID |
101
129
|`--cve`| Force identifier to be treated as a CVE ID |
102
130
|`--ghsa`| Force identifier to be treated as a GHSA ID |
103
131
|`-p, --package`| Force identifier to be treated as a package name |
104
-
|`-y, --yes`| Skip confirmation prompt for multiple patches |
105
132
|`--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`.
113
137
114
138
**Examples:**
115
139
```bash
@@ -144,24 +168,16 @@ Scan installed packages for available security patches. Since v3.0 `scan --sync`
144
168
socket-patch scan [options]
145
169
```
146
170
147
-
**Options:**
171
+
**Command-specific options** (plus all [Global Options](#global-options)):
148
172
| Flag | Description |
149
173
|------|-------------|
150
174
|`--apply`| Download and apply selected patches in JSON mode (non-interactive). Without it, `scan --json` is read-only. |
151
175
|`--prune`| Garbage-collect after the scan: remove manifest entries for uninstalled packages and orphan blob/diff/package-archive files. Off by default. |
152
176
|`--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`) |
|`--global-prefix <path>`| Custom path to global `node_modules`|
160
177
|`--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.
165
181
166
182
**Examples:**
167
183
```bash
@@ -199,20 +215,10 @@ Apply security patches from the local manifest.
199
215
socket-patch apply [options]
200
216
```
201
217
202
-
**Options:**
218
+
**Command-specific options** (plus all [Global Options](#global-options)):
203
219
| Flag | Description |
204
220
|------|-------------|
205
-
|`-d, --dry-run`| Verify patches without modifying files |
206
-
|`-s, --silent`| Only output errors |
207
221
|`-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: `.`) |
216
222
217
223
**Examples:**
218
224
```bash
@@ -241,23 +247,10 @@ Rollback patches to restore original files. If no identifier is given, all patch
241
247
socket-patch rollback [identifier] [options]
242
248
```
243
249
244
-
**Options:**
250
+
**Command-specific options** (plus all [Global Options](#global-options)):
245
251
| Flag | Description |
246
252
|------|-------------|
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 |
|`-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).
413
384
414
385
**Examples:**
415
386
```bash
@@ -426,6 +397,78 @@ socket-patch setup --dry-run
426
397
socket-patch setup --json -y
427
398
```
428
399
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`) |
|`--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
`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
+
429
472
## Scripting & CI/CD
430
473
431
474
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
452
495
453
496
## Environment Variables
454
497
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
+
455
500
| Variable | Description |
456
501
|----------|-------------|
457
502
|`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