From 2418944dd65a0c8f697f2b102d353f8c603f6bac Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 9 Oct 2026 17:30:43 +0000 Subject: [PATCH 1/2] Run 2 of 4 Gradle hosted Windows cells on PRs Each matching PR ran the 43-test hosted Gradle suite on Windows four times, once per Gradle line, at 28-42 min a cell: about 70% of the workflow's Windows minutes and its wall clock. Keep the oldest (6.9.4) and newest (9.8.0) lines on PRs and leave 7.6.6 and 8.14.3 hosted on Windows to the nightly and manual runs. ci.yml's e2e still runs hosted on all four lines on ubuntu on every PR and in the merge queue. Fixes #1300. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01VrgiQoDwt3vjxG2zNfZBAA --- .github/workflows/gradle-compatibility.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle-compatibility.yml b/.github/workflows/gradle-compatibility.yml index b8196642c..6bc58055c 100644 --- a/.github/workflows/gradle-compatibility.yml +++ b/.github/workflows/gradle-compatibility.yml @@ -42,7 +42,9 @@ name: Gradle patch compatibility # the same suites, filters, Gradle lines and JDKs on ubuntu on every PR and # in the merge queue. The ubuntu `extras` run on a PR only when it touches # Gradle code (`changes` below); every other PR gets them from the nightly -# (#1177). Windows cells run on every PR that matches `paths:`. +# (#1177). Windows cells run on every PR that matches `paths:`, except +# hosted on the middle Gradle lines (7.6.6, 8.14.3), which run nightly: a PR +# runs hosted on Windows on 6.9.4 and 9.8.0 only (#1300). on: pull_request: @@ -235,6 +237,16 @@ jobs: - os: ${{ github.event_name == 'pull_request' && 'macos-latest' || '' }} # ci.yml's `e2e` runs these ubuntu cells on every PR (#1177). - os: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || '' }} + # Windows hosted on a PR: only the oldest (6.9.4) and newest (9.8.0) + # lines. The middle two are ~40 min each, 40% of a PR run's Windows + # minutes; they run nightly, and ci.yml's `e2e` runs hosted on all + # four lines on ubuntu on every PR (#1300). + - os: ${{ github.event_name == 'pull_request' && 'windows-latest' || '' }} + gradle: '7.6.6' + mode: hosted + - os: ${{ github.event_name == 'pull_request' && 'windows-latest' || '' }} + gradle: '8.14.3' + mode: hosted runs-on: ${{ matrix.os }} timeout-minutes: 60 steps: &cell-steps From bc3d7f60bafb8b44fc43e1c63da3772794b0fc7a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 9 Oct 2026 17:42:24 +0000 Subject: [PATCH 2/2] Port #1301's minimist repin to unblock CI hosted-e2e (and the other live minimist suites) fail on every head: production now serves minimist@1.2.2 patch 642d7f02 while the tests pin 80630680 (#1293). This is #1301's change, applied verbatim; it becomes a no-op once #1301 lands. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01VrgiQoDwt3vjxG2zNfZBAA --- .../tests/e2e_hosted_production.rs | 4 +-- crates/socket-patch-cli/tests/e2e_npm.rs | 6 ++-- .../socket-patch-cli/tests/e2e_safety_pnpm.rs | 6 ++-- .../tests/e2e_vendored_production.rs | 4 +-- docs/testing/bun-compatibility.md | 2 +- scripts/backtest-bun.py | 2 +- scripts/backtest-vlt.py | 4 +-- scripts/tests/test_backtest_harnesses.py | 33 +++++++++++++++++++ 8 files changed, 47 insertions(+), 14 deletions(-) diff --git a/crates/socket-patch-cli/tests/e2e_hosted_production.rs b/crates/socket-patch-cli/tests/e2e_hosted_production.rs index 6c7ca6f07..f293592a0 100644 --- a/crates/socket-patch-cli/tests/e2e_hosted_production.rs +++ b/crates/socket-patch-cli/tests/e2e_hosted_production.rs @@ -33,7 +33,7 @@ //! //! | Ecosystem | PURL | Patch UUID | Advisory | //! |-----------|------|------------|----------| -//! | npm | `pkg:npm/minimist@1.2.2` | `80630680-4da6-45f9-bba8-b888e0ffd58c` | GHSA-xvch-5gv4-984h (CVE-2021-44906) | +//! | npm | `pkg:npm/minimist@1.2.2` | `642d7f02-ebc1-4ab0-99e2-07f5dd8463cb` | GHSA-xvch-5gv4-984h (CVE-2021-44906) | //! | PyPI | `pkg:pypi/urllib3@1.26.18` | *any of three* (see [`PYPI_UUIDS`]) | GHSA-gm62-xv2j-4w53 &co | //! | gem | `pkg:gem/activestorage@6.0.3` | *any of* [`GEM_UUIDS`] (six today; the sixth merges three advisories) | GHSA-m42x-37p3-fv5w (CVE-2020-8162), GHSA-w749-p3v6-hccq (CVE-2022-21831), GHSA-9xrj-h377-fr87 (CVE-2026-33195), GHSA-r4mg-4433-c7g3 (CVE-2025-24293), GHSA-xr9x-r78c-5hrm (CVE-2026-66066) | //! @@ -123,7 +123,7 @@ const PATCH_HOST: &str = "patch.socket.dev"; const NPM_PURL: &str = "pkg:npm/minimist@1.2.2"; const NPM_NAME: &str = "minimist"; const NPM_VERSION: &str = "1.2.2"; -const NPM_UUID: &str = "80630680-4da6-45f9-bba8-b888e0ffd58c"; +const NPM_UUID: &str = "642d7f02-ebc1-4ab0-99e2-07f5dd8463cb"; const PYPI_PURL: &str = "pkg:pypi/urllib3@1.26.18"; const PYPI_NAME: &str = "urllib3"; diff --git a/crates/socket-patch-cli/tests/e2e_npm.rs b/crates/socket-patch-cli/tests/e2e_npm.rs index 63de6c636..4df29c4d7 100644 --- a/crates/socket-patch-cli/tests/e2e_npm.rs +++ b/crates/socket-patch-cli/tests/e2e_npm.rs @@ -1,7 +1,7 @@ //! End-to-end tests for the npm patch lifecycle. //! //! These tests exercise the full CLI against the real Socket API, using the -//! **minimist@1.2.2** patch (UUID `80630680-4da6-45f9-bba8-b888e0ffd58c`), +//! **minimist@1.2.2** patch (UUID `642d7f02-ebc1-4ab0-99e2-07f5dd8463cb`), //! which fixes CVE-2021-44906 (Prototype Pollution). //! //! # Prerequisites @@ -26,14 +26,14 @@ use common::cache_env; // Constants // --------------------------------------------------------------------------- -const NPM_UUID: &str = "80630680-4da6-45f9-bba8-b888e0ffd58c"; +const NPM_UUID: &str = "642d7f02-ebc1-4ab0-99e2-07f5dd8463cb"; const NPM_PURL: &str = "pkg:npm/minimist@1.2.2"; /// Git SHA-256 of the *unpatched* `index.js` shipped with minimist 1.2.2. const BEFORE_HASH: &str = "311f1e893e6eac502693fad8617dcf5353a043ccc0f7b4ba9fe385e838b67a10"; /// Git SHA-256 of the *patched* `index.js` after the security fix. -const AFTER_HASH: &str = "043f04d19e884aa5f8371428718d2a3f27a0d231afe77a2620ac6312f80aaa28"; +const AFTER_HASH: &str = "ec956dcafb886f14315570bf3981d44aa12c561716abb46eed8b067aaa1f6bdf"; // --------------------------------------------------------------------------- // Helpers diff --git a/crates/socket-patch-cli/tests/e2e_safety_pnpm.rs b/crates/socket-patch-cli/tests/e2e_safety_pnpm.rs index 783e7337a..e70b3511d 100644 --- a/crates/socket-patch-cli/tests/e2e_safety_pnpm.rs +++ b/crates/socket-patch-cli/tests/e2e_safety_pnpm.rs @@ -11,7 +11,7 @@ //! view and the store entry byte-identical. //! //! Fixture: minimist@1.2.2 + its Socket patch (UUID -//! `80630680-4da6-45f9-bba8-b888e0ffd58c`, CVE-2021-44906) — same +//! `642d7f02-ebc1-4ab0-99e2-07f5dd8463cb`, CVE-2021-44906) — same //! pair `e2e_npm.rs` uses, so the BEFORE/AFTER hashes are known. //! //! Network: yes (pnpm install + socket-patch get). Toolchain: pnpm. @@ -24,12 +24,12 @@ mod common; use common::{assert_run_ok, git_sha256_file, has_command, pnpm_run, write_package_json}; -const NPM_UUID: &str = "80630680-4da6-45f9-bba8-b888e0ffd58c"; +const NPM_UUID: &str = "642d7f02-ebc1-4ab0-99e2-07f5dd8463cb"; /// Git-SHA-256 of the *unpatched* `index.js` shipped with minimist 1.2.2. const BEFORE_HASH: &str = "311f1e893e6eac502693fad8617dcf5353a043ccc0f7b4ba9fe385e838b67a10"; /// Git-SHA-256 of the *patched* `index.js` after the security fix. -const AFTER_HASH: &str = "043f04d19e884aa5f8371428718d2a3f27a0d231afe77a2620ac6312f80aaa28"; +const AFTER_HASH: &str = "ec956dcafb886f14315570bf3981d44aa12c561716abb46eed8b067aaa1f6bdf"; // ── Setup helpers ───────────────────────────────────────────────────── diff --git a/crates/socket-patch-cli/tests/e2e_vendored_production.rs b/crates/socket-patch-cli/tests/e2e_vendored_production.rs index 51a34a20f..53f2f2d9c 100644 --- a/crates/socket-patch-cli/tests/e2e_vendored_production.rs +++ b/crates/socket-patch-cli/tests/e2e_vendored_production.rs @@ -49,7 +49,7 @@ //! //! | Ecosystem | PURL | Patch UUID | Marker in the patched bytes | //! |-----------|------|------------|-----------------------------| -//! | npm | `pkg:npm/minimist@1.2.2` | `80630680-4da6-45f9-bba8-b888e0ffd58c` | `Socket Community Patch` header | +//! | npm | `pkg:npm/minimist@1.2.2` | `642d7f02-ebc1-4ab0-99e2-07f5dd8463cb` | `Socket Community Patch` header | //! | PyPI | `pkg:pypi/urllib3@1.26.18` | *any of three* (see [`PYPI_UUIDS`]) | `Socket Community Patch` header | //! | gem | `pkg:gem/activestorage@6.0.3` | *any of* [`GEM_PATCHES`] | `Socket Community Patch` header | //! @@ -137,7 +137,7 @@ const PROXY: &str = "https://patches-api.socket.dev"; const NPM_PURL: &str = "pkg:npm/minimist@1.2.2"; const NPM_NAME: &str = "minimist"; const NPM_VERSION: &str = "1.2.2"; -const NPM_UUID: &str = "80630680-4da6-45f9-bba8-b888e0ffd58c"; +const NPM_UUID: &str = "642d7f02-ebc1-4ab0-99e2-07f5dd8463cb"; const PYPI_PURL: &str = "pkg:pypi/urllib3@1.26.18"; const PYPI_NAME: &str = "urllib3"; diff --git a/docs/testing/bun-compatibility.md b/docs/testing/bun-compatibility.md index 26ef8e5d5..a65b4b96d 100644 --- a/docs/testing/bun-compatibility.md +++ b/docs/testing/bun-compatibility.md @@ -5,7 +5,7 @@ projects using text `bun.lock` or native binary `bun.lockb`. Real-Bun evidence b - **The native matrix** — `scripts/backtest-bun.py` runs real Bun releases against the public free Socket patch for `minimist@1.2.2` - (`80630680-4da6-45f9-bba8-b888e0ffd58c`) with the production CLI and patch + (`642d7f02-ebc1-4ab0-99e2-07f5dd8463cb`) with the production CLI and patch service, without a token or substitute service, and checks the INSTALLED bytes, lock stability, digest rejection and rollback on Linux, macOS and Windows ([workflow](../../.github/workflows/bun-compatibility.yml)). diff --git a/scripts/backtest-bun.py b/scripts/backtest-bun.py index 71020c4c8..8487c7b05 100644 --- a/scripts/backtest-bun.py +++ b/scripts/backtest-bun.py @@ -117,7 +117,7 @@ # former `vendored-detached` leg collapsed into `vendored`: same footprint. MODES = ['hosted', 'vendored'] PURL = 'pkg:npm/minimist@1.2.2' -UUID = '80630680-4da6-45f9-bba8-b888e0ffd58c' +UUID = '642d7f02-ebc1-4ab0-99e2-07f5dd8463cb' # The registry slot bun writes for a non-default registry: the full tarball URL. REGISTRY_SLOT = 'https://registry.npmjs.org/minimist/-/minimist-1.2.2.tgz' LOCAL_TUPLE_SPEC = f'minimist@.socket/vendor/npm/{UUID}/minimist-1.2.2.tgz' diff --git a/scripts/backtest-vlt.py b/scripts/backtest-vlt.py index 18ed56f9d..fb8533fa2 100644 --- a/scripts/backtest-vlt.py +++ b/scripts/backtest-vlt.py @@ -88,7 +88,7 @@ VERSIONS = ['0.0.0-16', '0.0.0-32', '1.0.0-rc.14', '1.0.0-rc.32', '1.0.4', '1.0.10', '1.2.0'] MODES = ['hosted', 'vendored', 'agent'] PURL = 'pkg:npm/minimist@1.2.2' -UUID = '80630680-4da6-45f9-bba8-b888e0ffd58c' +UUID = '642d7f02-ebc1-4ab0-99e2-07f5dd8463cb' NAME = 'minimist' VERSION = '1.2.2' TARGET = f'{NAME}@{VERSION}' @@ -1069,7 +1069,7 @@ def holds(self, root, lock_text, side): ok = True for copy_dir in self.copies(root, lock_text): for key, hashes in self.record['files'].items(): - path = copy_dir / key.split('/', 1)[1] + path = copy_dir / key.removeprefix('package/') digest = git_hash(path.read_bytes()) if path.is_file() else None details[str(path.relative_to(root))] = digest ok = ok and digest == hashes.get(f'{side}Hash') diff --git a/scripts/tests/test_backtest_harnesses.py b/scripts/tests/test_backtest_harnesses.py index bc2ee49dc..3ec7557aa 100644 --- a/scripts/tests/test_backtest_harnesses.py +++ b/scripts/tests/test_backtest_harnesses.py @@ -814,6 +814,39 @@ def test_shapes_are_depscan_capture_shapes(self): self.assertLessEqual(set(vlt.SHAPES), capture_names) +class VltInstalledBytesTests(unittest.TestCase): + def test_holds_checks_root_and_nested_files_with_optional_package_prefix(self): + contents = { + 'index.js': {'before': b'original entrypoint', 'after': b'patched entrypoint'}, + 'test/proto.js': {'before': b'original test', 'after': b'patched test'}, + } + for prefix in ('', 'package/'): + for side in ('before', 'after'): + with self.subTest(prefix=prefix, side=side), tempfile.TemporaryDirectory() as temp: + root = Path(temp) + package = root / 'node_modules' / 'minimist' + record = {'files': { + prefix + name: {s + 'Hash': vlt.git_hash(data) for s, data in sides.items()} + for name, sides in contents.items() + }} + cell = vlt.Cell({'out': root, 'record': record}, '1.2.0', 'vendored', 'direct') + expected = {} + for name, sides in contents.items(): + path = package / name + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(sides[side]) + expected[str(path.relative_to(root))] = vlt.git_hash(sides[side]) + self.assertEqual(cell.holds(root, '{}', side), (True, expected)) + other_side = 'after' if side == 'before' else 'before' + self.assertFalse(cell.holds(root, '{}', other_side)[0]) + + nested = package / 'test' / 'proto.js' + nested.write_bytes(b'corrupted') + self.assertFalse(cell.holds(root, '{}', side)[0]) + nested.unlink() + self.assertFalse(cell.holds(root, '{}', side)[0]) + + class VltConfigTests(unittest.TestCase): """write_vlt_json follows the DESIGN §8.3 per-era registry table."""