Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ vulnerabilities without waiting for an upstream release or upgrading the depende

The default workflow is **scan → install → vex**:

- `socket-patch scan` finds available patches and updates your dependency files to
use Socket-hosted patched packages.
- `socket-patch scan` finds available patches from project dependency files and
updates them to use Socket-hosted patched packages.
- Your package manager installs those packages using the updated references and
integrity pins. Commit the files that `scan` reports.
- `socket-patch vex` produces an OpenVEX document describing the vulnerabilities
Expand Down Expand Up @@ -53,13 +53,18 @@ installs, use that package manager's update command. The

## Quick start

From the root of a project with dependency files:
From the root of a project with a supported lockfile, including a fresh checkout
before dependencies are installed:

```sh
socket-patch scan --dry-run # preview available patches and edits
socket-patch scan # apply hosted references; never prompts
```

Agent mode needs installed packages. Some ecosystems need build-tool resolution
records first, such as sbt and scala-cli; see the
[ecosystem notes](docs/ecosystems.md).

Without an API token, the CLI uses Socket's public proxy for free patches.
To use your organization's patch tier, set `SOCKET_API_TOKEN`, or sign in with the
separate Socket CLI using `socket login`. See [configuration](docs/configuration.md).
Expand Down Expand Up @@ -119,6 +124,7 @@ socket-patch scan --max-new-patches 5 # introduce at most five new patche
socket-patch scan 'apps/*' # scan project directories in a monorepo
socket-patch get CVE-2024-12345 # target an advisory; hosted by default
socket-patch vendor # eject an existing hosted patch set
socket-patch repair # restore agent or vendored patch artifacts
socket-patch rollback # restore upstream dependencies
```

Expand Down
4 changes: 2 additions & 2 deletions crates/socket-patch-cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ fn unsupported_ecosystem_message(token: &str, supported: &str) -> String {

/// clap value-parser for `--vendor-source` / `SOCKET_VENDOR_SOURCE`.
///
/// Validates the token against [`VendorSource`] (`auto` | `service` | `build`,
/// case-insensitive) at parse time so a typo fails the command immediately
/// Validates the token against [`VendorSource`] (`service` or its `auto` alias,
/// case-insensitive; `build` is rejected) at parse time so a typo fails immediately
/// rather than at vendor time, and normalizes it to the canonical lowercase
/// tag. Mirrors [`parse_supported_ecosystem`]'s fail-loud-on-typo posture.
fn parse_vendor_source(s: &str) -> Result<String, String> {
Expand Down
43 changes: 28 additions & 15 deletions crates/socket-patch-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,21 @@ use socket_patch_core::utils::target::is_uuid_shaped;
version,
propagate_version = true,
after_help = "Patch a project:\n \
socket-patch scan Patch every dependency with a patch (hosted: rewrites lockfiles)\n \
socket-patch get Patch one package, CVE, GHSA or patch UUID\n \
socket-patch list Show the patches in this project\n\n\
socket-patch scan --dry-run Preview hosted changes from dependency files\n \
socket-patch scan Write hosted references for dependencies with patches\n \
socket-patch get Patch one package, CVE, GHSA or patch UUID\n \
socket-patch list Show the patches in this project\n\n\
Supported lockfiles work from a fresh checkout; install dependencies after scanning.\n\n\
Undo:\n \
socket-patch remove Unwind one patch (by PURL or UUID)\n \
socket-patch rollback Unwind every patch\n\n\
socket-patch remove Unwind one patch (by PURL or UUID)\n \
socket-patch rollback Unwind every patch\n\n\
Ship:\n \
socket-patch vex Emit an OpenVEX document for your vulnerability scanner\n \
socket-patch vendor Eject the patches into .socket/vendor/ for offline installs\n\n\
socket-patch vex Emit an OpenVEX document for your vulnerability scanner\n \
socket-patch vendor Eject the patches into .socket/vendor/ for offline installs\n\n\
Repair artifacts (agent and vendored):\n \
socket-patch repair Restore missing or corrupt artifacts; clean unused ones\n\n\
Agent mode (`scan --mode agent` edits installed files in place):\n \
socket-patch apply Re-apply .socket/manifest.json after each install (e.g. in CI)\n \
socket-patch repair Restore missing patch artifacts"
socket-patch apply Re-apply .socket/manifest.json after each install (e.g. in CI)"
)]
pub struct Cli {
#[command(subcommand)]
Expand All @@ -68,8 +71,17 @@ pub struct Cli {

#[derive(Subcommand)]
pub enum Commands {
/// Find patches for installed packages and apply them by rewriting
/// lockfiles to Socket-hosted patched packages
/// Find patches from project dependency files; write hosted lockfile
/// references by default (preview with --dry-run)
///
/// Rewrites lockfiles and related dependency files to use Socket-hosted
/// patched packages without prompting. Use `scan --dry-run` to preview
/// changes without writing them.
///
/// Supported lockfiles can be scanned from a fresh checkout before
/// installing dependencies. Some workflows require installed packages or
/// build-tool resolution records first: agent mode patches installed
/// files, and sbt / scala-cli need their build tool's resolution records.
Scan(commands::scan::ScanArgs),

/// Patch one package, CVE, GHSA or patch UUID (hosted mode by default)
Expand Down Expand Up @@ -102,11 +114,12 @@ pub enum Commands {
/// Agent mode: apply the patches in `.socket/manifest.json` in place
Apply(commands::apply::ApplyArgs),

/// Agent mode: download missing patch artifacts and clean up unused ones
/// Restore agent or vendored patch artifacts and clean up unused ones
///
/// Restores missing blobs and diff/package archives, rebuilds missing
/// or corrupt vendored artifacts, then deletes the artifacts nothing
/// references.
/// Downloads missing agent patch data and redownloads missing or corrupt
/// vendored artifacts using the existing vendor ledger, then deletes
/// unreferenced artifacts. A lost `.socket/vendor/state.json` cannot be
/// reconstructed; restore it from version control.
Repair(commands::repair::RepairArgs),

// Internal parse target of the root `--update` flag (see the rewrite
Expand Down
10 changes: 6 additions & 4 deletions crates/socket-patch-cli/tests/help_text_hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,17 @@ fn vendor_and_repair_summaries_read_as_one_line() {
);
assert!(
text.lines().any(|l| l
== " repair Agent mode: download missing patch artifacts and clean up unused ones"),
== " repair Restore agent or vendored patch artifacts and clean up unused ones"),
"{text}"
);
let repair = long_help(&["repair"]);
assert!(
repair.starts_with(
"Agent mode: download missing patch artifacts and clean up unused ones\n\n\
Restores missing blobs and diff/package archives, rebuilds missing or corrupt \
vendored artifacts, then deletes the artifacts nothing references.\n"
"Restore agent or vendored patch artifacts and clean up unused ones\n\n\
Downloads missing agent patch data and redownloads missing or corrupt \
vendored artifacts using the existing vendor ledger, then deletes \
unreferenced artifacts. A lost `.socket/vendor/state.json` cannot be \
reconstructed; restore it from version control.\n"
),
"{repair}"
);
Expand Down
34 changes: 31 additions & 3 deletions docs/migrating-to-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ existing scripts against the new CLI; the [changelog](../CHANGELOG.md) and

- Bare `scan` and `get` now patch in hosted mode when the project has no patch
state yet. `scan` never prompts; hosted and vendored `get` do not prompt either.
Use `scan --dry-run` for a preview or `--mode agent` to retain in-place patching.
`scan` discovers patches from project dependency files and writes hosted
references. Supported lockfiles work from a fresh checkout before installing
dependencies; install or resolve first where the selected
[mode or ecosystem](ecosystems.md) requires it, such as agent mode or
sbt / scala-cli. Use `scan --dry-run` for a preview or `--mode agent` to retain
in-place patching.
- A bare `scan` or `get` keeps the mode a project already uses: a project with a
vendor ledger (`.socket/vendor/state.json`) stays vendored, and one whose
`.socket/manifest.json` holds patches stays in agent mode. Switching modes needs an
Expand All @@ -25,8 +30,10 @@ existing scripts against the new CLI; the [changelog](../CHANGELOG.md) and
- `rollback` now removes patch records and unused artifacts as well as restoring
dependencies. Pass `--preserve-state` to retain local state for reuse.
- `scan` / `get --mode vendored` need no agent manifest. Commit
`.socket/vendor/state.json` with the artifacts. `repair` no longer reconstructs
a missing ledger from lockfiles.
`.socket/vendor/state.json` with the artifacts. `repair` restores missing agent
patch data or missing/corrupt vendored artifacts using existing records. It no
longer reconstructs a missing vendor ledger from lockfiles; restore the ledger
from version control.
- Vendored Cargo patches move into workspace-root `Cargo.toml` and use
`<version>+socket.<uuid>` versions. Re-running vendoring or repair migrates
older wiring. The tag is visible in `CARGO_PKG_VERSION`; see
Expand All @@ -42,6 +49,26 @@ existing scripts against the new CLI; the [changelog](../CHANGELOG.md) and
`SOCKET_ORG_SLUG` to get org patches. The org is resolved once per run, so an
embedded `--vex` no longer resolves it again.

## Service-only vendoring

v4 could build patched artifacts locally, with `auto` as the default acquisition
policy. v5 downloads new artifacts only from the patch service:

- `--vendor-source build` and `SOCKET_VENDOR_SOURCE=build` are rejected as usage
errors (exit 2). Remove that configuration or change it to `service`.
- `service` is the new default. `--vendor-source auto` and
`SOCKET_VENDOR_SOURCE=auto` remain compatibility aliases for `service`; they no
longer select a local build fallback.
- Missing or pending service artifacts, network errors, and integrity mismatches
do not trigger a local build fallback, even when the original package is installed.

Healthy committed artifacts can still be reused offline. Commit `.socket/vendor/`,
including `state.json`, and the dependency-file changes the CLI reports. Installing
those patched packages needs neither Socket API access nor the Socket Patch CLI;
unpatched dependencies still need their normal registry, mirror, or cache.
Fetching a new artifact or redownloading a missing or corrupt one requires service
access. See [vendoring and offline installs](usage.md#vendoring-and-offline-installs).

## JSON output

Every `--json` failure now reports its top-level `error` as an object,
Expand Down Expand Up @@ -181,6 +208,7 @@ whole root, not a `vendor_jvm_degraded` warning on mixed Maven + Gradle roots.
| `scan --apply` | `scan --mode agent` |
| `scan --vendor` | `scan --mode vendored` |
| `get --no-apply` | `get --save-only` (`SOCKET_SAVE_ONLY` is unchanged) |
| `--vendor-source build`, `SOCKET_VENDOR_SOURCE=build` | Remove the setting or use `service`; `auto` is now a service-only alias |
| `socket-patch download` | `socket-patch get` |
| `socket-patch gc` | `socket-patch repair` |
| `--download-mode`, `SOCKET_DOWNLOAD_MODE` | No replacement; patch content is always fetched as per-file blobs |
Expand Down
19 changes: 12 additions & 7 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ flags, response fields, and diagnostic codes live in the

## Select patches

A bare `scan` applies patches without prompting, in the mode the project already
uses: hosted for a new project, vendored or agent if `.socket/` already holds patches
in that mode. Pass `--mode` to choose or switch modes. Use `--dry-run` to inspect
what it would change, and `--json` for a machine-readable result:
A bare `scan` discovers patches from project dependency files and applies them
without prompting, in the mode the project already uses: hosted (writing hosted
references) for a new project, vendored or agent if `.socket/` already holds
patches in that mode. Pass `--mode` to choose or switch modes. Supported lockfiles
work from a fresh checkout before installing dependencies. Agent mode needs
installed packages, and some ecosystems need resolution records first (see
[sbt and scala-cli](#sbt-and-scala-cli) and the [ecosystem notes](ecosystems.md)).
Use `--dry-run` to inspect what would change, and `--json` for a machine-readable
result:

```sh
socket-patch scan --dry-run --json
Expand Down Expand Up @@ -103,8 +108,8 @@ owns archive construction, including Yarn Berry cache checksums. Python
vendoring accepts both wheels and source distributions supplied by the service.

`--vendor-source service` is the default. `auto` remains an alias for the same
behavior; `build` is rejected. A missing artifact, pending build, network error,
or integrity mismatch fails without a local build fallback. Healthy committed
behavior; `build` is rejected. Missing or pending service artifacts, network errors,
and integrity mismatches do not trigger a local build fallback. Healthy committed
artifacts can be reused offline.

`repair` redownloads missing or corrupt artifacts and checks them against the
Expand Down Expand Up @@ -226,7 +231,7 @@ The removed `setup` command is covered in the [migration guide](migrating-to-v5.
| `rollback [PURL\|UUID\|PATH]...` | Restore selected patches, or all patches when no target is given, and remove their local state |
| `remove <PURL\|UUID>` | Restore and remove one patch |
| `vendor --revert` | Undo vendoring from its recorded edits and remove the vendored artifacts |
| `repair` | Restore missing patch data or damaged vendored artifacts and clean unused data |
| `repair` | Restore missing agent patch data or missing/corrupt vendored artifacts using existing records, and clean unused data |
| `scan --mode agent --prune` | Patch discovered packages and remove records for dependencies that left the project |

Use `--dry-run` to preview. `rollback --preserve-state` and
Expand Down
Loading