Skip to content

Hosted yarn classic rescan and VEX accept a pin written by v4.0.0 whose patched package.json adds a dependency the lock doesn't have, so yarn installs the patched package without it #1462

Open

Description

[agent] Found by the scheduled Yarn classic (1.x) bug-hunt routine (ledger #304).

Summary

This is the hosted-mode counterpart of #1379, which covered vendored mode only.

Since #1328 / #1363 (#591), a fresh hosted scan refuses a yarn classic pin when the served tarball's package.json depends on a descriptor that yarn.lock doesn't lock (redirect_yarn_classic_dep_manifest_unlocked). A lock that v4.0.0 already pinned in that state isn't caught, though. That matters because v4.0.0 is the current npm latest, so every existing hosted user upgrades from it.

Impact

yarn install --frozen-lockfile exits 0 and installs the patched package without the dependency its own package.json declares. A real patch that requires that dependency crashes at runtime. Meanwhile CI sees a green scan and a not_affected VEX statement.

Repro (Linux, yarn 1.22.22, local mock API)

The mock serves a left-pad@1.3.0 patch whose package/package.json adds "is-number": "^7.0.0". The grant carries sha512 + sha1. The mock is the ledger's run-18 one plus an ADD_DEP switch.

M=http://127.0.0.1:8787; export SOCKET_API_URL=$M SOCKET_PROXY_URL=$M SOCKET_PATCH_SERVER_URL=$M
API="--api-url $M --proxy-url $M --patch-server-url $M"
echo '{"name":"p","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json
yarn install
npx @socketsecurity/socket-patch@4.0.0 scan --mode hosted --json --yes $API   # pins resolved "<mock>/…/left-pad-1.3.0.tgz#<sha1>"; no is-number block
socket-patch scan --mode hosted --json --yes $API      # main: status success, events [applied], warnings [berry_migration_risk only]
rm -rf node_modules && yarn install --frozen-lockfile  # exit 0; node_modules: left-pad only
grep is-number node_modules/left-pad/package.json      # "is-number": "^7.0.0" declared, not installed
socket-patch vex --output v.json $API                  # exit 0, not_affected
socket-patch scan --mode hosted --vex v2.json --json --yes $API   # exit 0, not_affected

Control: the same main scan on a fresh, unpinned lock refuses correctly (redirect_unconfirmed plus redirect_yarn_classic_dep_manifest_unlocked, with the lock untouched).

Expected vs actual

  • Expected: CLI_CONTRACT says redirect_yarn_classic_dep_manifest_unlocked fires when "the served tarball's own package.json depends on a descriptor no yarn.lock block is keyed by… The dep is not pinned and never confirmed". An existing pin in that state should be flagged on rescan (warning, non-success, or un-pinned), not confirmed as applied. vex shouldn't attest a pin yarn installs without the patch's dependencies. That's the hosted equivalent of what Fix yarn classic check of dangling descriptors (#1379) #1388 added to vendor --check.
  • Actual: with a sha1 grant, the rescan reports applied with no warning. With a no-sha1 grant, it warns but keeps the pin and exits success. In both shapes vex / scan --vex give not_affected.

Matrix (main 15c2c83, Linux; lock pinned by v4.0.0)

yarn sha1 grant: rescan no-sha1 grant: rescan frozen install vex / scan --vex
1.7.0 applied, no warning not run dep missing, exit 0 not_affected
1.10.1 applied, no warning not run dep missing, exit 0 not_affected
1.22.22 applied, no warning (×3) warns, pin kept, success dep missing, exit 0 not_affected

macOS and Windows weren't probed. The logic is platform-independent.

First bad version

The hole has existed since #1328 (the #591 fix) landed. v5.0.0 includes that fix and has the same gap. v4.0.0 is what wrote the dangling pins: before #591 was fixed, hosted mode never checked the served manifest.

Suspect code

Activity

  1. mikolalysenko commented on Oct 13, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triage: priority:p1 (yarn classic, npm family). Not a duplicate: #1379 (fixed by #1388) covered vendored mode only; this is the hosted rescan/VEX side, where an artifact already pinned with a sha1 is never fetched in select_classic_artifacts, so the #591 served-manifest check never runs. No open PR addresses it.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 13, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue (shared root cause: the hosted yarn classic rescan never re-reads the served package.json of an artifact the lock already pins, and a refused pin left by an earlier release stays in the lock and is attested). Branch: agent/fix-yarn-classic-pinned-manifest-check. Claim-ID: 2026-10-13T02:21:15Z-bb537d


    Generated by Claude Code

  3. mikolalysenko commented on Oct 13, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft PR: #1463


    Generated by Claude Code

  4. added 4 commits that reference this issue on Oct 13, 2026
    5e9277b
    daca7bd
    04db3f5
    fdde961
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions