Skip to content

Hosted yarn classic scan --vex attests not_affected when an npm: alias copy of the patched package was skipped, while standalone vex refuses the same lock #1081

Description

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

Summary

Take a yarn 1.22.22 project that depends on the patched package directly and through an npm: alias ("left-pad": "1.3.0", "x": "npm:left-pad@1.3.0"). yarn 1.22.22 writes two lock blocks, left-pad@1.3.0: and "x@npm:left-pad@1.3.0":.

A hosted scan pins the direct block and leaves the alias block alone, with redirect_yarn_classic_alias_skipped (documented). After the next install, node_modules/x is the unpatched upstream copy.

  • Standalone vex sees this. It warns patched_ref_unattributable ("that copy stays UNPATCHED and nothing is attested") and exits 2 with nothing written, both lock-only and after the install.
  • The in-run scan --mode hosted --vex carries the same patched_ref_unattributable warning in vex.warnings[], yet writes a not_affected statement for pkg:npm/left-pad@1.3.0.

So the run's own envelope says "nothing is attested" next to a document that attests.

Impact

CI that runs scan --mode hosted --vex publishes a not_affected OpenVEX statement for a vulnerability whose code still ships unpatched under the alias name. The scan exits 0.

Repro (Linux, main 05ecc6e, yarn 1.22.22, local mock patch API on :8787)

mkdir p && cd p
echo '{"name":"p","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0","x":"npm:left-pad@1.3.0"}}' > package.json
yarn install
socket-patch scan --mode hosted --vex in.json --json --yes --api-url http://127.0.0.1:8787 --org o --api-token x > s.json
#  → exit 0; s.json: redirect.warnings = [redirect_yarn_classic_alias_skipped]
#                     vex.warnings    = [patched_ref_unattributable … "nothing is attested"]
#    in.json: one statement, pkg:npm/left-pad@1.3.0 "not_affected"
socket-patch vex --output v.json ...     # → exit 2, manifest_not_found, same patched_ref_unattributable warning, nothing written
rm -rf node_modules && yarn install --frozen-lockfile
head -c 30 node_modules/left-pad/index.js   # patched
head -c 30 node_modules/x/index.js          # UNPATCHED

A file:./left-pad-1.3.0.tgz direct dep instead of the registry one behaves the same way.

Expected vs actual

Matrix (Linux, Node 22; each cell twice)

yarn lock shape in-run scan --vex standalone vex (lock-only / post-install) node_modules/x
1.22.22 two blocks not_affected refuses, exit 2 unpatched
1.22.22, file: tarball + alias two blocks not_affected refuses, exit 2 unpatched
1.10.1 / 1.19.0 one merged block left-pad@1.3.0, "x@npm:left-pad@1.3.0":, pinned as a whole not_affected — patched (correct)

In my runs, every release from 1.0 to 1.22.21 (checked 1.12.3, 1.17.3, 1.19.0, 1.21.1, 1.22.0/4/10/15/17/19/21) merges the two keys into one block. Only 1.22.22, the current latest and corepack's default, writes them separately.

Suspect code

crates/socket-patch-cli/src/commands/scan/hosted.rs:1337: params.assume_applied drops the uuids in rewrite.bundled_skipped_uuids (#469), but not those whose copy the rewriter skipped as an alias (redirect_yarn_classic_alias_skipped). So the confirmed purl is attested without verification, although vex/discover flags it patched_ref_unattributable. Berry's redirect_yarn_berry_alias_skipped may take the same path (not checked).

Related: #828 (the same lock state also can't be unwound by rollback / remove; commented there).

Activity

  1. mikolalysenko commented on Oct 7, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triage: priority:p1 (Yarn classic, npm-family). Not a duplicate. Open PR #1033 (arch-fix/vex-false-attest) doesn't touch assume_applied's handling of redirect_yarn_classic_alias_skipped (I checked its diff), so it doesn't cover this. Related: #828 (the same alias lock state on rollback / remove), which has a different cause.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 8, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Re-checked on main ea09714 (after #1033 / #1044 / #1083): still reproduces, ×2, on yarn 1.22.22.

    {"left-pad":"1.3.0","lp":"npm:left-pad@1.3.0"} → scan --mode hosted --vex vex.json --json exits 0 and pins left-pad@1.3.0:. It warns redirect_yarn_classic_alias_skipped and the in-run VEX statement is not_affected / inline_mitigations_already_exist. After rm -rf node_modules && yarn install --frozen-lockfile, node_modules/left-pad is patched and node_modules/lp is not. A standalone vex on the same lock refuses with exit 2 (the "copy stays UNPATCHED and nothing is attested" warning). So the in-run and standalone paths still disagree.


    Generated by Claude Code

  3. mikolalysenko commented on Oct 8, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue (with #1158; shared root cause: the hosted rewrite reports no per-patch signal for a yarn npm: alias copy it skipped, so the in-run VEX (assume_applied) and the takeover planner (Takeover::unpinned) both treat the purl as fully pinned). Branch: agent/fix-yarn-alias-skip-partial-pin. Claim-ID: 2026-10-08T21:44:16Z-5531e1


    Generated by Claude Code

  4. mikolalysenko commented on Oct 8, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft PR: #1180


    Generated by Claude Code

  5. added
    v5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.
    on Oct 9, 2026
  6. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    v5 release blocker (P1). The normal scan --vex workflow must not attest an npm alias copy that the same scan explicitly skipped. Standalone and embedded VEX need the same outcome; PR #1180 is pending.

    This follows the maintainer's release scope: one normally completing CLI instance, prioritizing valid-lockfile patch/install behavior, compatibility, and actionable CLI UX.

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

    agent:claimedagent:triagedbugSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentpm:yarn-classicYarn classic (1.x)priority:p1v5-blockerMust resolve before v5: public interface/migration or ordinary patch-install-undo failure.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions