Repository navigation
Yarn berry renamed-copy detection ignores a portal: / link: copy with an absolute path, so hosted and vendored scans succeed and every VEX path attests not_affected while that copy installs unpatched #1540
Description
[agent] Found by the scheduled Yarn Berry (2+) bug-hunt routine (ledger #305).
Summary
#1517 (for #1516) reads renamed yarn copies wherever yarn installs them from, and fails closed when it can't read one. One berry shape is still left out: a portal: or link: dependency with an absolute path, e.g. "lp2": "portal:/home/me/shared/left-pad". Yarn berry installs it normally and links node_modules/lp2 to that directory (left-pad@1.3.0). socket-patch never reads it:
CopyRef::read_pathreturnsNonefor any anchored path (copy.rs:46), on purpose, because a lock is untrusted input.- A
file:copy with an unread identity is then kept as an unidentified copy at its lock version, which is fail-closed. That works: absolutefile:/…/lpdirandfile:/…/lp.tgzboth warnredirect_copy_unpatchedand block VEX. - A
Linkedcopy has no lock version (0.0.0-use.local), so an unread one is dropped instead:vendor/yarn_copies.rs:111(None if matches!(source, CopyRef::Linked(_)) => continue) andvex/discover/yarn.rs:878(record_copiesonly records unidentified non-Linkedcopies).
So an absolute portal: / link: copy fails open. The scan reports success with no copy warning, and VEX attests not_affected from the in-run scan, from the lock-only vex, and even from post-install vex with node_modules/lp2 present and unpatched.
Impact
The VEX document says not_affected for pkg:npm/left-pad@1.3.0 while the project links an unpatched left-pad@1.3.0 into node_modules/lp2. This is the same false attestation as #939 / #1516, reached through an absolute path instead of a relative one. Absolute portal: / link: paths are normal in local monorepo and dev setups, since berry keeps the path as written in both package.json and yarn.lock.
Repro (Linux, Node 22, main a3f56f7, yarn 4.18.1 and 4.0.2, node-modules linker)
I used the repo's e2e_redirect_yarn_berry_build.rs hosted fixture with its wiremock patch API, which serves a left-pad@1.3.0 patch that prepends /* SOCKET-PATCHED */ to index.js.
mkdir -p ext/lpdir proj
tar xzf left-pad-1.3.0.tgz -C ext/lpdir --strip-components=1
cd proj
# package.json: {"dependencies": {"left-pad": "1.3.0", "lp2": "portal:/ABS/PATH/ext/lpdir"}}
printf 'nodeLinker: node-modules\n' > .yarnrc.yml
yarn install
# yarn.lock: "lp2@portal:/ABS/PATH/ext/lpdir::locator=…": version 0.0.0-use.local
socket-patch scan --mode hosted --json --yes --vex v1.json … # exit 0, status success, codes: [vex_hosted_unverified] only
# v1.json: not_affected pkg:npm/left-pad@1.3.0
# fresh checkout (package.json, yarn.lock, .yarnrc.yml):
socket-patch vex --output v2.json … # exit 0, not_affected
yarn install --immutable # exit 0
grep -c SOCKET-PATCHED node_modules/left-pad/index.js # 1
grep -c SOCKET-PATCHED node_modules/lp2/index.js # 0 <- unpatched left-pad@1.3.0
socket-patch vex --output v3.json … # exit 0, not_affected (post-install)Replace portal: with link: and the result is the same. scan --mode vendored behaves the same too: exit 0, no vendor_copy_unpatched, and all three VEX paths attest.
Controls on the same main build, where everything works:
- The relative
portal:../ext/lpdir, and the member-relativeportal:../../../ext/lpdirfrompackages/a, warnredirect_copy_unpatched(hosted) orvendor_copy_unpatched(vendored), withvex_omitted. Lock-only and post-installvexrefuse. - Absolute
file:/ABS/ext/lpdirandfile:/ABS/ext/lp.tgzare recorded as unidentified copies:redirect_copy_unpatched,vex_omitted, andvexexits 2.
Expected vs actual
- docs/ecosystems.md, "yarn copies under another dependency name (classic & berry)": "The copy is read wherever yarn installs it from …. A copy whose package can't be read … is treated as possibly any package … and
vexnever attests the package from that lock while the copy is there." - Expected: an absolute
portal:/link:copy fails closed, like an absolutefile:copy. Either name it as a possible copy and block VEX for the versions the lock wires, or read it. Reading is safe for a linked directory, which yarn has already linked intonode_modules; the post-install tree could also be read throughnode_modules/<dep>/package.json. - Actual: the copy is dropped silently. The scan reports
success, and in-run, lock-only and post-install VEX all attestnot_affected.
Matrix (Linux; hosted and vendored unless noted; main a3f56f7)
| yarn | portal:/abs |
link:/abs |
file:/abs dir / tgz |
relative portal:../ext |
member portal:../../../ext |
|---|---|---|---|---|---|
| 4.18.1 | fail (hosted ×2, vendored ×1) | fail (hosted) | pass (fail-closed, hosted) | pass | pass (hosted) |
| 4.0.2 | fail (hosted) | untested | untested | pass (run 41, PR #1517) | untested |
I didn't probe macOS or Windows. On Windows, is_anchored also catches C:\… and UNC spellings, so the same path should fail there too. Yarn 2/3 are refused by hosted and vendored mode.
First bad: not a regression. Every renamed berry copy was missed before #1489 (#939). #1489 and #1517 deliberately leave absolute paths unread, and the Linked exemption turns that into fail-open.
Suspect code
crates/socket-patch-core/src/formats/yarn/copy.rs:46:read_pathreturnsNonefor anchored paths.crates/socket-patch-core/src/vendor/yarn_copies.rs:111: an unreadLinkedcopy iscontinued (dropped).crates/socket-patch-core/src/vex/discover/yarn.rs:878:record_copiesskips unidentifiedLinkedcopies ("has no version, and is left alone").
Activity
mikolalysenko commentedon Oct 14, 2026
[agent] Triaged: priority:p1 (Yarn berry, npm family). Confirmed on main:
CopyRef::read_pathreturnsNonefor anchored paths, and an unreadCopyRef::Linkedcopy is dropped (vendor/yarn_copies.rscontinue,vex/discover/yarn.rsrecord_copies) instead of kept as an unidentified copy likefile:. It follows #1516 / #1517 but takes a different path (absoluteportal:/link:), so it is not a duplicate. No open PR addresses it.Generated by Claude Code
mikolalysenko commentedon Oct 14, 2026
[agent] Claiming this issue (shared root cause: an unread absolute
portal:/link:yarn berry copy is dropped instead of kept as an unidentified fail-closed copy). Branch: agent/fix-yarn-berry-abs-linked-copy. Claim-ID: 2026-10-14T22:20:41Z-85edbcGenerated by Claude Code
mikolalysenko commentedon Oct 14, 2026
[agent] Draft fix PR: #1551
Generated by Claude Code
Block VEX for unread yarn portal:/link: copies
Test hosted scan names absolute portal copies
Only unread portal copies count as any version