Skip to content

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

Closed

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_path returns None for 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: absolute file:/…/lpdir and file:/…/lp.tgz both warn redirect_copy_unpatched and block VEX.
  • A Linked copy 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) and vex/discover/yarn.rs:878 (record_copies only records unidentified non-Linked copies).

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-relative portal:../../../ext/lpdir from packages/a, warn redirect_copy_unpatched (hosted) or vendor_copy_unpatched (vendored), with vex_omitted. Lock-only and post-install vex refuse.
  • Absolute file:/ABS/ext/lpdir and file:/ABS/ext/lp.tgz are recorded as unidentified copies: redirect_copy_unpatched, vex_omitted, and vex exits 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 vex never attests the package from that lock while the copy is there."
  • Expected: an absolute portal: / link: copy fails closed, like an absolute file: 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 into node_modules; the post-install tree could also be read through node_modules/<dep>/package.json.
  • Actual: the copy is dropped silently. The scan reports success, and in-run, lock-only and post-install VEX all attest not_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_path returns None for anchored paths.
  • crates/socket-patch-core/src/vendor/yarn_copies.rs:111: an unread Linked copy is continued (dropped).
  • crates/socket-patch-core/src/vex/discover/yarn.rs:878: record_copies skips unidentified Linked copies ("has no version, and is left alone").

Activity

  1. mikolalysenko commented on Oct 14, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged: priority:p1 (Yarn berry, npm family). Confirmed on main: CopyRef::read_path returns None for anchored paths, and an unread CopyRef::Linked copy is dropped (vendor/yarn_copies.rs continue, vex/discover/yarn.rs record_copies) instead of kept as an unidentified copy like file:. It follows #1516 / #1517 but takes a different path (absolute portal: / link:), so it is not a duplicate. No open PR addresses it.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 14, 2026

    @mikolalysenko
    CollaboratorAuthor

    [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-85edbc


    Generated by Claude Code

  3. mikolalysenko commented on Oct 14, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft fix PR: #1551


    Generated by Claude Code

  4. added 3 commits that reference this issue on Oct 14, 2026
    2d3dac8
    af452c2
    7a3fb87
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions