[agent] Found by the scheduled Yarn classic (1.x) bug-hunt routine (ledger #304).
Summary
In a yarn-classic project that uses an offline mirror (yarn-offline-mirror "./mirror" in .yarnrc, the documented way to commit dependencies for offline or air-gapped CI), scan --mode hosted rewrites the lock entry to the hosted tarball and reports success. After that, every install of the project fails.
Yarn 1 names and looks up offline-mirror files by the basename of the resolved URL. The hosted URL …/patch/npm/left-pad/1.3.0/<token>/<uuid>/left-pad-1.3.0.tgz has the same basename, left-pad-1.3.0.tgz, as the upstream tarball already sitting in the mirror. So:
yarn install / yarn install --frozen-lockfile (yarn ≥ 1.10) takes the upstream mirror file and checks it against the new patched integrity → Integrity check failed for "left-pad", exit 1.
yarn install --offline (yarn ≥ 1.7) → Can't make a request in offline mode ("…/left-pad-1.3.0.tgz"), exit 1, because the patched tarball never reaches the mirror.
The scan prints no warning, and nothing in the docs mentions offline mirrors. Vendored mode on the same project works (the patched file: tarball is installed, online and --offline). Only hosted mode is affected.
Impact
- Hosted mode, which v5 makes the default, breaks every install, frozen or not and online or offline, for any yarn-classic project with a populated offline mirror. The user gets an integrity error that points at Socket's own URL.
- The only ways out are hand-deleting the mirror file (and it has to be the right one) or reverting the redirect.
- A silent success in the scan output (
status: success, redirect.redirected: 1, warnings: []).
Repro (Linux, main f6b7fb9, yarn 1.22.22)
mkdir app && cd app
echo '{"name":"b","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json
printf 'yarn-offline-mirror "./mirror"\n' > .yarnrc
yarn install # mirror/left-pad-1.3.0.tgz (upstream bytes)
socket-patch scan --mode hosted --json --yes --api-url $MOCK --org test-org --api-token fake
# → status success, redirect.redirected 1, no warnings
# yarn.lock: resolved "http://…/patch/npm/left-pad/1.3.0/<token>/<uuid>/left-pad-1.3.0.tgz#f6cceb…"
# integrity sha512-rsCT4g… (patched tarball)
# fresh checkout of package.json + yarn.lock + .yarnrc + mirror/ + .socket/, empty cache:
yarn install --frozen-lockfile # exit 1
# error http://…/left-pad-1.3.0.tgz: Integrity check failed for "left-pad"
# (computed integrity doesn't match our records, got "sha512-XI5MPz… sha1-W4o6d2…") ← the upstream tarball
yarn install --frozen-lockfile --offline # exit 1: Can't make a request in offline mode ("…/left-pad-1.3.0.tgz")
Control: the same project with no socket-patch step installs fine from the mirror, both online and --offline (1.7+).
$MOCK is a local mock of the patch API. Its hosted URL uses the production shape (/patch/npm/<name>/<version>/<token>/<uuid>/<name>-<version>.tgz, as in vex.rs / scan/mod.rs tests), so the basename collision also happens against patch.socket.dev.
Expected vs actual
- Expected: docs/ecosystems.md lists yarn classic as fully supported in hosted mode. After a successful hosted scan, the next install (frozen or not) should install the patched bytes. If a mirror is configured, socket-patch should do one of these: put the patched tarball in the mirror under the basename yarn will look up (replacing or moving aside the upstream file), fail closed with a
redirect_yarn_classic_offline_mirror-style warning or refusal and point to --mode vendored, or at least warn. The bug-hunt filing bar treats "a rewrite that makes the next frozen install fail" as a bug.
- Actual: the lock is rewired with no warning, and every install fails with an integrity error.
OS × version
| OS |
yarn |
online install (--frozen-lockfile) |
--offline install |
control, no socket-patch |
| Linux |
1.0.2 / 1.6.0 |
n/a: these releases install nothing from a mirror even without socket-patch (exit 0, empty node_modules); a yarn / Node 22 limitation |
n/a |
installs nothing |
| Linux |
1.7.0 |
pass (patched; pre-integrity-line yarn refetches) |
fail (offline mode) |
pass |
| Linux |
1.9.4 |
pass (patched) |
fail (offline mode) |
pass |
| Linux |
1.10.1 |
fail (Integrity check failed) |
fail |
pass |
| Linux |
1.17.3 |
fail |
fail |
pass |
| Linux |
1.22.22 |
fail |
fail |
pass |
| Linux (probe) |
1.10.1 / 1.22.22 |
fail (Integrity check failed) |
fail |
pass |
| macOS (probe) |
1.10.1 / 1.22.22 |
fail (Integrity check failed) |
fail |
pass |
| Windows (probe) |
1.10.1 / 1.22.22 |
fail (Integrity check failed) |
fail |
pass |
Vendored mode with the same mirror: pass on 1.10.1 and 1.22.22 (online and --offline). Released 4.0.0 behaves the same, so this isn't a recent regression.
Suspect code
crates/socket-patch-core/src/patch/redirect/mod.rs:3670 (rewrite_yarn_classic). It only rewrites resolved / integrity and never reads .yarnrc / .npmrc (yarn-offline-mirror), so the mirror isn't considered. grep -ri offline.mirror over the repo finds no handling or documentation.
Probe run (ubuntu/macos/windows × yarn 1.10.1/1.22.22): https://github.com/SocketDev/socket-patch/actions/runs/36761888480
[agent] Found by the scheduled Yarn classic (1.x) bug-hunt routine (ledger #304).
Summary
In a yarn-classic project that uses an offline mirror (
yarn-offline-mirror "./mirror"in.yarnrc, the documented way to commit dependencies for offline or air-gapped CI),scan --mode hostedrewrites the lock entry to the hosted tarball and reports success. After that, every install of the project fails.Yarn 1 names and looks up offline-mirror files by the basename of the
resolvedURL. The hosted URL…/patch/npm/left-pad/1.3.0/<token>/<uuid>/left-pad-1.3.0.tgzhas the same basename,left-pad-1.3.0.tgz, as the upstream tarball already sitting in the mirror. So:yarn install/yarn install --frozen-lockfile(yarn ≥ 1.10) takes the upstream mirror file and checks it against the new patchedintegrity→Integrity check failed for "left-pad", exit 1.yarn install --offline(yarn ≥ 1.7) →Can't make a request in offline mode ("…/left-pad-1.3.0.tgz"), exit 1, because the patched tarball never reaches the mirror.The scan prints no warning, and nothing in the docs mentions offline mirrors. Vendored mode on the same project works (the patched
file:tarball is installed, online and--offline). Only hosted mode is affected.Impact
status: success,redirect.redirected: 1,warnings: []).Repro (Linux, main
f6b7fb9, yarn 1.22.22)Control: the same project with no socket-patch step installs fine from the mirror, both online and
--offline(1.7+).$MOCKis a local mock of the patch API. Its hosted URL uses the production shape (/patch/npm/<name>/<version>/<token>/<uuid>/<name>-<version>.tgz, as invex.rs/scan/mod.rstests), so the basename collision also happens against patch.socket.dev.Expected vs actual
redirect_yarn_classic_offline_mirror-style warning or refusal and point to--mode vendored, or at least warn. The bug-hunt filing bar treats "a rewrite that makes the next frozen install fail" as a bug.OS × version
--frozen-lockfile)--offlineinstallnode_modules); a yarn / Node 22 limitationVendored mode with the same mirror: pass on 1.10.1 and 1.22.22 (online and
--offline). Released 4.0.0 behaves the same, so this isn't a recent regression.Suspect code
crates/socket-patch-core/src/patch/redirect/mod.rs:3670(rewrite_yarn_classic). It only rewritesresolved/integrityand never reads.yarnrc/.npmrc(yarn-offline-mirror), so the mirror isn't considered.grep -ri offline.mirrorover the repo finds no handling or documentation.Probe run (ubuntu/macos/windows × yarn 1.10.1/1.22.22): https://github.com/SocketDev/socket-patch/actions/runs/36761888480