Skip to content

Commit 8b468d9

Browse files
committed
Merge remote-tracking branch 'origin/main' into audit/test-review
2 parents ef041ed + ed435b4 commit 8b468d9

37 files changed

Lines changed: 4846 additions & 76 deletions

.github/workflows/ci.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,16 @@ jobs:
417417
suite: e2e_composer
418418
- os: ubuntu-latest
419419
suite: e2e_nuget
420+
# Cargo project-local [patch]-redirect backend + fail-closed guard.
421+
# `guard_build_integration` is hermetic (a shell stub + `cargo build
422+
# --offline` against a zero-dep path dep), so it exercises the
423+
# build.rs-panic-aborts-a-real-build seam with no network.
424+
# `e2e_cargo_coexist`'s real-cargo proofs fetch a crate (cached) and
425+
# skip on fetch failure. Both suites are `#[cfg(unix)]`.
426+
- os: ubuntu-latest
427+
suite: guard_build_integration
428+
- os: ubuntu-latest
429+
suite: e2e_cargo_coexist
420430
# The live-API smoke suites (e2e_npm, e2e_pypi, e2e_gem,
421431
# e2e_scan) are intentionally NOT in the PR matrix — their
422432
# `#[ignore]`-gated tests hit the real public proxy at

CHANGELOG.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,49 @@ in this file — see `.github/workflows/release.yml` (`version` job).
1616

1717
### Added
1818

19+
- **Project-local cargo `[patch]`-redirect backend (local mode).** Patching a
20+
Rust dependency from the registry cache no longer mutates the shared
21+
`$CARGO_HOME` registry in place. Instead `apply` writes a project-local
22+
patched **copy** under `.socket/cargo-patches/<name>-<version>/` and a managed
23+
`[patch.crates-io]` entry (+ `[env] SOCKET_PATCH_ROOT`) into
24+
`.cargo/config.toml`, so patches are project-scoped and the registry stays
25+
pristine for sibling projects. `rollback` cleanly drops the entry + copy
26+
(leaving `setup` state — the guard dependency + `[env]` — intact).
27+
`apply --check` is a new read-only, lock-free, offline auditor that verifies
28+
the committed copies/config match the manifest **and** cross-checks
29+
`Cargo.lock` (flagging a patched dependency that silently resolved to an
30+
unpatched version); it exits non-zero on drift (for CI / GitHub-App use).
31+
Vendored crates (`vendor/`) and `--global` cargo keep the existing in-place
32+
`.cargo-checksum.json` rewrite path unchanged. **`cargo` is now a default
33+
feature** (alongside the always-on npm + PyPI support), so released binaries and
34+
a plain `cargo install socket-patch-cli` patch Rust dependencies and run the
35+
guard out of the box; `golang`/`maven`/`composer`/`nuget`/`deno` remain opt-in.
36+
A binary built `--no-default-features` (no cargo) now fails `apply --check`
37+
closed rather than reporting "in sync", so it can never make the guard pass
38+
vacuously.
39+
- **`socket-patch-guard` crate + `setup` cargo support.** `socket-patch setup`
40+
now also configures Rust projects: it adds a tiny `socket-patch-guard`
41+
dependency (a normal `[dependencies]` entry, not a `[build-dependencies]` one,
42+
so cargo always compiles it and runs its build script) to every workspace
43+
member and writes `[env] SOCKET_PATCH_ROOT`. The guard's build script runs `socket-patch apply --check`
44+
on every relevant `cargo build` and is **fail-closed**: if the committed
45+
patched copies are out of sync with `.socket/manifest.json` (a stale copy, or
46+
a patched dependency that resolved to an unpatched version), the build
47+
**fails** rather than silently compiling stale/unpatched sources — closing the
48+
CI footgun where a one-shot build could ship an unpatched binary. The fix is
49+
run-order-independent (it checks the static committed state, not when the
50+
build script happens to run). It is a single fail-closed mode with no
51+
`warn`/`off` escape: on drift it regenerates the copies then fails the build
52+
with a "re-run" message (the retry is clean), and an unrecoverable state or a
53+
missing `socket-patch` CLI also fails the build. In normal use the guard never
54+
fires, since changing a patch goes through `get`/`apply` (which regenerate the
55+
copies). The user's own `build.rs` is never touched. For CI, run
56+
`socket-patch apply --check --ecosystems cargo` as an explicit pipeline gate.
57+
`setup --check` / `setup --remove` cover the
58+
round-trip. *(A guarded repo requires `socket-patch` on the build machine —
59+
wire it into apps/workspaces you control, not a published library. Pre-GA:
60+
`socket-patch-guard` will be published to crates.io; airgapped users vendor
61+
it.)*
1962
- **Inline OpenVEX generation on `apply` and `scan` via `--vex <path>`.** A
2063
single successful `apply`/`scan` can now both patch and emit the OpenVEX
2164
0.2.0 attestation, instead of requiring a separate `socket-patch vex` step.
@@ -28,6 +71,16 @@ in this file — see `.github/workflows/release.yml` (`version` job).
2871
command exit non-zero even when the apply/scan itself succeeded, surfacing a
2972
stable error code in the envelope.
3073

74+
### Changed
75+
76+
- **Local cargo `apply` now redirects instead of patching in place.** Registry
77+
crates patched by a previous (in-place) version leave a mutated shared
78+
registry + rewritten `.cargo-checksum.json` behind; the new local backend
79+
never touches the registry, so those stay dirty until cargo re-fetches.
80+
`apply` now prints a one-line **warning** when it detects such a crate
81+
(suppressed under `--offline`, so the build-time guard stays quiet) and points
82+
at restoring the pristine copy. No automatic registry cleanup is performed.
83+
3184
## [3.2.0] — 2026-05-29
3285

3386
A repo-wide correctness, security, and filesystem-safety hardening pass: every

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
[workspace]
2-
members = ["crates/socket-patch-core", "crates/socket-patch-cli"]
2+
members = [
3+
"crates/socket-patch-core",
4+
"crates/socket-patch-cli",
5+
"crates/socket-patch-guard",
6+
]
37
resolver = "2"
48

59
[workspace.package]

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,11 @@ pip install socket-patch
6363
cargo install socket-patch-cli
6464
```
6565

66-
By default this builds with npm and PyPI support. For additional ecosystems:
66+
By default this builds with npm, PyPI, and Cargo support. For additional
67+
ecosystems:
6768

6869
```bash
69-
cargo install socket-patch-cli --features cargo,golang,maven,composer,nuget
70+
cargo install socket-patch-cli --features golang,maven,composer,nuget,deno
7071
```
7172

7273
## Quick Start

crates/socket-patch-cli/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ regex = { workspace = true }
2828
tempfile = { workspace = true }
2929

3030
[features]
31-
default = []
31+
# Shipped defaults: npm + PyPI are always compiled in (no feature gate); `cargo`
32+
# is on by default so released binaries and `cargo install socket-patch-cli`
33+
# patch Rust deps and run the build-time guard out of the box. The remaining
34+
# ecosystems stay opt-in. Build `--no-default-features` for a minimal
35+
# (npm + PyPI only) binary — its `apply --check` then fails closed.
36+
default = ["cargo"]
3237
cargo = ["socket-patch-core/cargo"]
3338
golang = ["socket-patch-core/golang"]
3439
maven = ["socket-patch-core/maven"]

0 commit comments

Comments
 (0)