Skip to content

Commit 1ddf04e

Browse files
committed
Simplify v5 help and docs and hide API tokens in help
1 parent 69542db commit 1ddf04e

15 files changed

Lines changed: 209 additions & 315 deletions

File tree

‎Cargo.toml‎

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -76,22 +76,14 @@ strip = true
7676
lto = true
7777
opt-level = "s"
7878

79-
# CI-only profile for the test-release job. Inherits the shipped profile's
80-
# semantics (opt-level = "s", debug-assertions off, overflow-checks off) —
81-
# which is what test-release exists to validate — but drops
82-
# the full-LTO link: ~23m of that job's ~29m was LTO-relinking 159 test
83-
# binaries, and LTO relinks are structurally uncacheable. release.yml still
84-
# builds the real full-LTO [profile.release] for every shipped target.
79+
# Test release semantics without the cost of full-LTO links for every test binary.
80+
# Shipped binaries still use [profile.release].
8581
[profile.ci-release]
8682
inherits = "release"
8783
lto = false
8884
strip = "none" # unstripped test binaries => usable backtraces on failure
8985

90-
# The benchmark gate's build (crates/socket-patch-bench, .github/workflows/
91-
# bench.yml): the shipped profile's codegen (opt-level = "s", no debug
92-
# assertions) so timings track what users run, with thin instead of full
93-
# LTO so CI can afford to build both sides of a comparison. Unstripped, so
94-
# a profiler can symbolize it.
86+
# Benchmark with release codegen, faster thin-LTO links, and profiler symbols.
9587
[profile.perf]
9688
inherits = "release"
9789
lto = "thin"
@@ -103,19 +95,12 @@ strip = "none"
10395
inherits = "release"
10496
lto = "thin"
10597

106-
# Test-execution speed: `cargo test` builds dependencies with the dev
107-
# profile; at opt-level 0 the hash/compression hot loops are 10-100x
108-
# slower (the self_update fixtures gzip and sha256-hash the multi-MB debug
109-
# CLI binary per test: ~403s debug vs ~2s release). Workspace members are NOT matched by "*" — they stay
110-
# opt-level 0, so incremental compile speed, debugging, and llvm-cov line
111-
# fidelity (reports filter to workspace crates) are unchanged. Dependencies
112-
# keep debug-assertions and overflow-checks ON — only codegen opt changes.
98+
# Optimize dependencies for test speed. Workspace crates stay unoptimized;
99+
# debug assertions and overflow checks remain enabled everywhere.
113100
[profile.dev.package."*"]
114101
opt-level = 1
115102

116-
# The measured hot path gets full optimization: archive building
117-
# (flate2/zip over multi-MB payloads), SHA hashing in fixtures and in the
118-
# CLI's own verify paths.
103+
# Fully optimize hashing and compression, the test fixtures' hot paths.
119104
[profile.dev.package.sha2]
120105
opt-level = 3
121106
[profile.dev.package.sha1]
@@ -141,13 +126,7 @@ opt-level = 3
141126
[profile.dev.package.zip]
142127
opt-level = 3
143128

144-
# macOS debug builds use unpacked split-debuginfo: every linked binary —
145-
# including each of the ~90 e2e test executables — pins its per-codegen-unit
146-
# .o files in target/debug/deps, and cargo never garbage-collects the
147-
# generations superseded by lockfile/toolchain bumps (this grew target/ to
148-
# 99 GB). Line tables keep panic backtraces readable while dropping the bulk
149-
# of the retained DWARF; for a full-fidelity debugger session, override with
150-
# CARGO_PROFILE_DEV_DEBUG=full. Applies to test/bench profiles via
151-
# inheritance.
129+
# Keep backtraces readable without retaining full DWARF for every test binary.
130+
# Use CARGO_PROFILE_DEV_DEBUG=full for debugger sessions.
152131
[profile.dev]
153132
debug = "line-tables-only"

‎README.md‎

Lines changed: 33 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,9 @@
11
# Socket Patch
22

3-
Apply security fixes to the dependency versions your project already uses.
4-
Socket provides patches for specific package versions so you can address known
5-
vulnerabilities without waiting for an upstream release or upgrading the dependency.
6-
7-
The default workflow is **scan → install → vex**:
8-
9-
- `socket-patch scan` finds available patches from project dependency files and
10-
updates them to use Socket-hosted patched packages.
11-
- Your package manager installs those packages using the updated references and
12-
integrity pins. Commit the files that `scan` reports.
13-
- `socket-patch vex` produces an OpenVEX document describing the vulnerabilities
14-
addressed by those patches.
15-
16-
Use `socket-patch vendor` to put the selected patched packages in your repository
17-
when installs must work without Socket's patch server.
3+
Apply security fixes to the dependency versions your project already uses,
4+
without waiting for an upstream release or upgrading the dependency.
5+
Socket Patch updates dependency files to use patched packages, which you install
6+
with your normal package manager.
187

198
> This branch documents the v5 prerelease. Installation commands below select the
209
> latest published release, which may have different behavior. To try this branch,
@@ -29,11 +18,9 @@ Install a standalone binary on macOS or Linux:
2918
curl -fsSL https://install.socket.dev/patch | sh
3019
```
3120

32-
The installer verifies the download against the release's `SHA256SUMS` and installs
33-
in `/usr/local/bin` or `~/.local/bin`. To choose a directory or release, pass
34-
`SOCKET_PATCH_INSTALL_DIR` or `SOCKET_PATCH_VERSION` to `sh` after the pipe.
35-
See the [installer source](scripts/install.sh) and
36-
[mirror configuration](docs/installer-hosting.md).
21+
The installer verifies release checksums and installs in `/usr/local/bin` or
22+
`~/.local/bin`. See the [installer options](scripts/install.sh) for a custom
23+
directory or version, and [mirror setup](docs/installer-hosting.md).
3724

3825
On Windows, extract a `socket-patch-*-pc-windows-msvc.zip` archive from
3926
[GitHub Releases](https://github.com/SocketDev/socket-patch/releases) into a directory
@@ -43,13 +30,12 @@ on your `PATH`, or install through npm:
4330
npm install -g @socketsecurity/socket-patch
4431
```
4532

46-
Cargo users can build and install the published CLI with
47-
`cargo install socket-patch-cli`. All distributions support the same ecosystems;
48-
you do not need Node.js or Rust to use the standalone binary.
33+
Cargo users can run `cargo install socket-patch-cli`. The standalone binary
34+
requires neither Node.js nor Rust. All installation methods support the same
35+
ecosystems; see the [support matrix](docs/ecosystems.md) for platform details.
4936

5037
For standalone installs, run `socket-patch --update` to update. For npm or Cargo
51-
installs, use that package manager's update command. The
52-
[platform matrix](docs/ecosystems.md#supported-platforms) lists release targets.
38+
installs, use that package manager's update command.
5339

5440
## Quick start
5541

@@ -58,38 +44,25 @@ before dependencies are installed:
5844

5945
```sh
6046
socket-patch scan --dry-run # preview available patches and edits
61-
socket-patch scan # apply hosted references; never prompts
47+
socket-patch scan # update dependency files; never prompts
6248
```
6349

64-
Agent mode needs installed packages. Some ecosystems need build-tool resolution
65-
records first, such as sbt and scala-cli; see the
66-
[ecosystem notes](docs/ecosystems.md).
67-
68-
Without an API token, the CLI uses Socket's public proxy for free patches.
69-
To use your organization's patch tier, set `SOCKET_API_TOKEN`, or sign in with the
70-
separate Socket CLI using `socket login`. See [configuration](docs/configuration.md).
71-
72-
A scan with no available patches means the catalog has no applicable patch for
73-
this run. It is **not** a finding that the project has no vulnerabilities.
74-
75-
Review and commit the files the scan changed. Hosted mode keeps no patch ledger;
76-
its state is in the project's lockfiles, manifests, and package-manager configuration.
77-
For example, an npm project may change both `package-lock.json` and `.npmrc`:
50+
Review and commit the dependency and configuration files the scan reports. Then
51+
install the patched packages and generate OpenVEX for your vulnerability scanner:
7852

7953
```sh
80-
git diff
81-
git add package-lock.json .npmrc
82-
git commit -m "Apply Socket security patches"
83-
npm ci
54+
npm ci # use your project's normal install command
8455
socket-patch vex --output socket.vex.json
8556
socket-patch list
8657
```
8758

88-
Use your project's normal install command in place of `npm ci`. Some package
89-
managers reuse installed or cached upstream packages; follow any reinstall warning
90-
from the CLI and the [ecosystem notes](docs/ecosystems.md). Generate VEX after
91-
installing to verify the copies your build consumes, then pass the document to your
92-
VEX-aware vulnerability scanner.
59+
Follow any reinstall warning from the CLI: some package managers reuse cached
60+
upstream packages. Agent mode needs installed packages; sbt and scala-cli need
61+
resolution records first. See the [ecosystem notes](docs/ecosystems.md).
62+
63+
Free patches need no token. For organization patches, set `SOCKET_API_TOKEN` or
64+
use the separate Socket CLI's `socket login`. See [configuration](docs/configuration.md).
65+
A scan with no available patches does **not** mean the project has no vulnerabilities.
9366

9467
## Patch modes
9568

@@ -105,39 +78,26 @@ Hosted and vendored installs do not need an install hook or the Socket Patch CLI
10578
Once a project holds vendored or agent-mode patches, a bare `scan` or `get` keeps
10679
that mode; pass `--mode` to switch.
10780

108-
The CLI supports npm, PyPI, Cargo, Go, RubyGems, Maven (including sbt, Mill and
109-
scala-cli builds), Composer, NuGet, and Deno.
110-
Mode and package-manager support vary: Deno uses agent mode, for example. Check the
111-
[ecosystem support matrix](docs/ecosystems.md) before choosing a mode.
112-
113-
Vendored Maven reactors and Gradle 6.8+ builds are supported. See
114-
[JVM vendoring](docs/design/maven-vendoring.md) for supported project shapes,
115-
cache behavior, and offline checks. sbt 0.13.18+ builds are wired through one
116-
generated `socket-patch.sbt` (hosted) or `socket-patch-vendor.sbt` (vendored);
117-
see [Scala build tools](docs/ecosystems.md#scala-build-tools-sbt-mill-scala-cli).
81+
Supported ecosystems include npm, PyPI, Cargo, Go, RubyGems, Maven, Composer,
82+
NuGet, and Deno. Check the [support matrix](docs/ecosystems.md) for available
83+
modes and package-manager limitations.
11884

11985
## Common commands
12086

12187
```sh
122-
socket-patch scan --package lodash # limit selection to a package
123-
socket-patch scan --max-new-patches 5 # introduce at most five new patches
124-
socket-patch scan 'apps/*' # scan project directories in a monorepo
125-
socket-patch get CVE-2024-12345 # target an advisory; hosted by default
88+
socket-patch scan --package lodash # limit selection to a package
89+
socket-patch scan --max-new-patches 5 # introduce at most five new patches
90+
socket-patch scan 'apps/*' # scan projects in a monorepo
91+
socket-patch get pkg:npm/lodash@4.17.20 # target one package version
12692
socket-patch vendor # eject an existing hosted patch set
12793
socket-patch repair # restore agent or vendored patch artifacts
94+
socket-patch rollback lodash # restore one package to upstream
12895
socket-patch rollback # restore upstream dependencies
12996
```
13097

131-
`get` also accepts a GHSA, patch UUID, PURL, or exact package name (every installed
132-
version of that name is searched; near names are only suggested). `scan` selects from
133-
patches your account can download, preferring the highest severity, then the most
134-
advisories fixed, then the newest publication date. Existing patches are upgraded
135-
only by a better-ranked patch.
136-
137-
Hosted rollback resolves upstream metadata and generally needs network access.
138-
Where restoration is unsupported, including hosted binary `bun.lockb`, the CLI
139-
refuses the change and gives a version-control recovery hint. See
140-
[usage and recovery](docs/usage.md).
98+
`get` also accepts a CVE, GHSA, patch UUID, or exact package name. Hosted rollback
99+
generally needs network access; some formats require restoring files from version
100+
control. See [usage and recovery](docs/usage.md).
141101

142102
Use `socket-patch <command> --help` for options and
143103
[`socket.yml`](docs/configuration.md#repository-patch-policy) for a shared rollout policy.

‎crates/socket-patch-cli/CLI_CONTRACT.md‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ uppercase letter settles on its exact-case package among case-distinct ones
6464

6565
`get <name>` searches every installed version of the matched name (within
6666
`--ecosystems`) and prints `Matched: …` on stderr. With no exact match in a
67-
nonempty inventory it is `no_match` (exit 0, no patch-search API call) and, in
67+
nonempty inventory it is `noMatch` (exit 0, no patch-search API call) and, in
6868
human mode, suggests up to five near names (`Did you mean: …?`) without acting on
69-
them. An empty inventory is `no_packages` (exit 0). `--ecosystems` also filters
69+
them. An empty inventory is `noPackages` (exit 0). `--ecosystems` also filters
7070
advisory/purl search results and UUID selection before any patch is written; a
71-
UUID outside the selected ecosystems is `not_found` (exit 0).
71+
UUID outside the selected ecosystems is `notFound` (exit 0).
7272

7373
`remove` / `rollback` accept the same names and versionless purls against manifest
7474
records, vendor-ledger entries and hosted pins; CVE/GHSA ids match no record
@@ -1248,7 +1248,11 @@ The v3.0 legacy names `SOCKET_PATCH_PROXY_URL`, `SOCKET_PATCH_DEBUG` and `SOCKET
12481248

12491249
## JSON output shapes
12501250

1251-
Every `--json` invocation emits a single JSON object that follows the **unified envelope** below. The envelope was introduced in v3.0; older per-command shapes are deprecated. See `src/json_envelope.rs` for the source of truth; its unit tests pin the serialized names, and each command's e2e tests assert the envelope it emits. The `tests/cli_parse_*.rs` files pin the parsed clap arguments, not this shape (a few, such as `cli_parse_list.rs`, also spot-check `list`'s envelope).
1251+
Every command's `--json` output is a single object using the envelope below.
1252+
v5 removes the older per-command shapes. Argument-parsing errors and invalid
1253+
`--cwd`, `--global-prefix`, or `--manifest-path` values still exit 2 with stderr
1254+
output and no JSON. `src/json_envelope.rs` defines the serialized names; each
1255+
command's integration tests check its output.
12521256

12531257
**One error shape (v5.0, MAJOR).** On every command, every `--json` failure is a full envelope (`command`, `status: "error"`, `dryRun`, `events`, `summary`) whose top-level `error` is a `{code, message}` object — the envelope's `EnvelopeError`. `code` is a stable snake_case tag (see [Top-level `EnvelopeError` codes](#top-level-envelopeerror-codes)); `message` is for humans. No command prints a top-level `errorCode` any more (it moved into `error.code`). Per-event keys are unchanged: `events[*].error` / `events[*].errorCode` stay strings.
12541258

‎crates/socket-patch-cli/src/args.rs‎

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
1-
//! Shared CLI arguments flattened into every subcommand.
2-
//!
3-
//! `GlobalArgs` defines the flags that apply uniformly across every
4-
//! `socket-patch` subcommand. Each subcommand `#[command(flatten)]`s this
5-
//! struct into its own `Args` struct so the surface stays consistent.
6-
//!
7-
//! Subcommands that don't actually use a given global flag still accept it
8-
//! silently (no-op). See `CLI_CONTRACT.md` for the full contract.
9-
//!
10-
//! Precedence for every flag: CLI arg > env var > default.
11-
//!
12-
//! All env-var names use the `SOCKET_*` prefix.
1+
//! Shared CLI flags and their `SOCKET_*` environment bindings.
2+
//! Commands accept unused flags as no-ops. See `CLI_CONTRACT.md` for their scope
3+
//! and configuration precedence.
134
145
use std::path::{Path, PathBuf};
156

@@ -23,14 +14,7 @@ use socket_patch_core::crawlers::Ecosystem;
2314
use socket_patch_core::telemetry::TelemetryAuth;
2415
use socket_patch_core::vendor::{VendorServiceConfig, VendorSource};
2516

26-
/// clap value-parser for each `--ecosystems` / `SOCKET_ECOSYSTEMS` token.
27-
///
28-
/// Rejects any name that is not a supported ecosystem, so typos fail
29-
/// loudly instead of silently matching nothing.
30-
///
31-
/// Without this, an unsupported name parsed fine and was then silently
32-
/// dropped by `partition_purls`/`crawl_ecosystems`, so the user got a
33-
/// "0 patches" result with no hint that the ecosystem name was the cause.
17+
/// Reject unknown ecosystems before they can produce a misleading empty scan.
3418
fn parse_supported_ecosystem(s: &str) -> Result<String, String> {
3519
if Ecosystem::all().iter().any(|e| e.cli_name() == s) {
3620
Ok(s.to_string())
@@ -55,27 +39,12 @@ fn unsupported_ecosystem_message(token: &str, supported: &str) -> String {
5539
}
5640
}
5741

58-
/// clap value-parser for `--vendor-source` / `SOCKET_VENDOR_SOURCE`.
59-
///
60-
/// Validates the token against [`VendorSource`] (`service` or its `auto` alias,
61-
/// case-insensitive; `build` is rejected) at parse time so a typo fails immediately
62-
/// rather than at vendor time, and normalizes it to the canonical lowercase
63-
/// tag. Mirrors [`parse_supported_ecosystem`]'s fail-loud-on-typo posture.
42+
/// Validate the service source and normalize its compatibility alias at parse time.
6443
fn parse_vendor_source(s: &str) -> Result<String, String> {
6544
VendorSource::parse(s).map(|v| v.as_tag().to_string())
6645
}
6746

68-
/// clap value-parser for boolean flags backed by an env var.
69-
///
70-
/// Identical to clap's stock `BoolishValueParser` (case-insensitive
71-
/// `true/false`, `yes/no`, `on/off`, `1/0`) **except** that an empty string is
72-
/// treated as `false` rather than rejected.
73-
///
74-
/// Without this, an exported-but-empty env var — e.g. `SOCKET_OFFLINE=` or
75-
/// `SOCKET_JSON=`, which shells and CI routinely set to mean "unset" — made
76-
/// clap abort the whole command with `invalid value '' for '--offline': value
77-
/// was not a boolean`. Every bool flag here reads such an env var, so a single
78-
/// stray empty var crashed every subcommand before it could do any work.
47+
/// Parse boolish environment values, treating an exported empty value as false.
7948
pub(crate) fn parse_bool_flag(s: &str) -> Result<bool, String> {
8049
match s.trim().to_ascii_lowercase().as_str() {
8150
"" | "n" | "no" | "f" | "false" | "off" | "0" => Ok(false),
@@ -128,7 +97,12 @@ pub struct GlobalArgs {
12897
pub api_url: Option<String>,
12998

13099
/// Socket API token. Absence selects the public patch proxy.
131-
#[arg(help_heading = GLOBAL_OPTIONS, long = "api-token", env = "SOCKET_API_TOKEN")]
100+
#[arg(
101+
help_heading = GLOBAL_OPTIONS,
102+
long = "api-token",
103+
env = "SOCKET_API_TOKEN",
104+
hide_env_values = true
105+
)]
132106
pub api_token: Option<String>,
133107

134108
/// Organization slug. Auto-resolved when omitted and a token is set.
@@ -143,8 +117,7 @@ pub struct GlobalArgs {
143117
#[arg(help_heading = GLOBAL_OPTIONS, long = "proxy-url", env = "SOCKET_PROXY_URL")]
144118
pub proxy_url: Option<String>,
145119

146-
/// Restrict to these ecosystems (comma-separated). Names that are not
147-
/// supported ecosystems are rejected.
120+
/// Restrict to these ecosystems (comma-separated).
148121
#[arg(
149122
help_heading = GLOBAL_OPTIONS,
150123
long = "ecosystems",
@@ -197,8 +170,7 @@ pub struct GlobalArgs {
197170
)]
198171
pub patch_server_url: Option<String>,
199172

200-
/// Strict airgap: never contact the network. Operations that need remote
201-
/// data fail loudly when this is set.
173+
/// Disable network access; fail if remote data is needed.
202174
#[arg(
203175
help_heading = GLOBAL_OPTIONS,
204176
long,

‎crates/socket-patch-cli/src/commands/rollback.rs‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ use crate::ui::{plural, StatusLine};
4141

4242
#[derive(Args)]
4343
pub struct RollbackArgs {
44-
/// What to roll back: a package PURL, a patch UUID, or a path glob
45-
/// (e.g. `packages/foo`, `apps/**`) selecting the patches whose
44+
/// Package names, PURLs, UUIDs, or paths; omit to restore all patches.
45+
///
46+
/// Paths and globs (e.g. `packages/foo`, `apps/**`) select patches whose
4647
/// installed copies live under matching paths. Multiple targets union.
4748
/// Omit to roll back ALL patch state — in-place patches, vendored
4849
/// patches, and hosted lockfile redirects.
@@ -60,12 +61,13 @@ pub struct RollbackArgs {
6061
#[command(flatten)]
6162
pub common: GlobalArgs,
6263

63-
/// Restore the system (files and lockfiles) but PRESERVE the local
64+
/// Keep local patch records and artifacts for later reuse.
65+
///
66+
/// Restore the system (files and lockfiles) but preserve the local
6467
/// patch state for a later re-apply: manifest entries are kept,
6568
/// vendored artifacts and their ledger entries are kept (only the
6669
/// lockfile wiring is reverted), and no blob/archive cleanup runs.
67-
/// Hosted redirects have no preservable local state — their ledger
68-
/// records describe live wiring and are dropped with it either way.
70+
/// Hosted references have no local state to preserve.
6971
#[arg(
7072
long = "preserve-state",
7173
env = "SOCKET_PRESERVE_STATE",

0 commit comments

Comments
 (0)