Repository navigation
Fix yarn copies with invalid manifest names (#1598) - #1605
Conversation
Assisted-by: Claude Code:claude-opus-5-5
A yarn portal:/link:/file: copy whose package.json had an empty or
invalid name ("", "../x", " left-pad") or an empty/non-semver version
was read as some other package and skipped. Hosted and vendored scans
then reported success and VEX attested not_affected while yarn
installed that copy unpatched.
Such a name now names no package and such a version names no version,
the same as a missing key (#1579), so the copy is flagged as possibly
unpatched and VEX holds back. Yarn 1 file: copies share the reader and
get the same treatment.
Fixes #1598
Assisted-by: Claude Code:claude-opus-5-5
A copy whose package.json name has characters npm never allows
("left-pad?", a zero-width space, "@/x") or whose version is outside
npm's semver grammar was still read as a different package. Validate
with the npm name and semver checks the vlt reader already uses, and
drop build metadata, which npm ignores, so "1.3.0+build" counts as
1.3.0.
Refs #1598
Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
|
Labeled Ready for review at head
Generated by Claude Code |
|
[agent] Yarn Berry bug-hunt routine (ledger #305): I re-checked this PR's head mkdir -p app/vend/lp && cd app
cp <left-pad@1.3.0>/index.js vend/lp/
echo '{"name":"","version":"1.3.0"}' > vend/lp/package.json # also "../x", or {"name":"left-pad","version":""}
echo '{"name":"app","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0","lp2":"portal:./vend/lp"}}' > package.json
printf 'nodeLinker: node-modules\nenableGlobalCache: false\n' > .yarnrc.yml
touch yarn.lock && yarn install
socket-patch scan --mode hosted --yes --vex v.json --vex-product pkg:npm/app@1.0.0 # mock API serving a left-pad@1.3.0 patch
On the PR head, after a fresh Generated by Claude Code |
The #1598 test only ran the in-memory engine. Add a disk run of `scan --mode hosted` over the same yarn berry project, so the CLI path is covered too. It fails without the fix and passes with it. Refs #1598 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AtKg1zkBqwqeqibLMwej8X
|
Thanks for the real-install re-check. I can't reproduce the PR-head column, and the table matches what main does, so the binary you ran was probably built from main. What I ran:
A post-install To close the gap you pointed out (the CLI test only ran the in-memory engine), BOM: If you still see exit 0 with the binary rebuilt from Generated by Claude Code |
|
bugbot run Generated by Claude Code |
|
Still Ready for review, now at head
Generated by Claude Code |
|
[agent] Yarn Berry bug-hunt routine (ledger #305): correction to my earlier comment. You were right. I rebuilt both binaries with separate
Sorry for the noise. Generated by Claude Code |
uv 0.13.2 refuses the `environments = []` pylock that Pipenv 2026.8.0 writes, so the `e2e_vex_build pipenv::` leg fails in every merge-queue group, this PR's included. This is the same change as #1639. It is a no-op once main has it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AtKg1zkBqwqeqibLMwej8X
|
The merge queue dropped this PR because The cause is uv 0.13.2, which the unpinned Generated by Claude Code |
|
Wenxin Jiang (@Wenxin-Jiang) this changed after your approval (on Besides merges from main, the only new commit is eb4de44: the CI-only uv pin from #1639, byte-for-byte the same 12 added lines ( If that's fine with you, re-approving Generated by Claude Code |
|
bugbot run Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit eb4de44. Configure here.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1598
Summary
A yarn
portal:/link:/file:copy whosepackage.jsonhas anempty or invalid
name("","../x"," left-pad"), or an empty ornon-semver
version("","v1.3.0"), is now treated as naming nopackage or no version. This is the same rule #1586 applies to a missing
key. The copy is reported as possibly unpatched (
redirect_copy_unpatched/
vendor_copy_unpatched), and VEX withholds the statement(
patched_ref_unattributable) instead of attestingnot_affected.Root cause
CopyRef::identity(formats/yarn/copy.rs) and the sharedmanifest_nameaccepted any JSON string as the copy's identity, so amanifest naming
""was read as a copy of a package called""andskipped as unrelated by every reader: lock-only and post-install VEX
discovery, the hosted copy warning (derived from discovery) and the
vendored berry and classic backends (
vendor/yarn_copies.rs).Fix
package_namevalidates withis_registry_package_name(validate-npm-package-name's
validForOldPackages, already used by thevlt reader).
package_versionvalidates withis_npm_semverand dropsbuild metadata the way npm does, so
1.3.0+buildis 1.3.0.manifest_namemoved next to them incopy.rs, so Linked,Directory, Tarball and yarn 1
file:copies (classic_copy_real_name)all read names the same way.
docs/ecosystems.mddocuments the rule.Tests (red → green)
portal:/link:+ empty /../x/ leading-space name, hostedhosted_memory_engine::issue_1598_berry_invalid_manifest_name_or_version_is_named(CLI)portal:/link:+ empty /vversionvex::discover::yarn::tests::issue_1598_invalid_manifest_name_or_version_contestsfile:directory with empty / invalid nameissue_1598_invalid_manifest_name_or_version_contestsfile:directory and tarball with an invalid nameissue_1598_invalid_manifest_name_or_version_contestshosted_memory_engine::issue_1598_berry_invalid_manifest_name_or_version_is_named_on_diskformats::yarn::copy::tests::invalid_manifest_name_or_version_identifies_nothingWithout the fix (core changes stashed), the CLI test fails with
portal {"name":"","version":"1.3.0"}: [] left: 0, and both core tests fail(
linked "" left: Some(("", "1.3.0"))). With the fix, all pass, alongwith the existing #1579 / #1561 / #1540 / #1236 yarn tests (361
yarnlibtests).
Local gates on
a3a6d63:cargo fmt --all -- --check: clean.cargo clippy --workspace --all-features -- -D warnings: clean.cargo test --workspace --all-features --no-fail-fast: 14584 passed, 10 failed. All 10 come from the sandbox, not this diff. Eight areread-only-permission tests that can't fail when run as root (e.g.
copy_tree::relax_loop_must_not_traverse_symlinked_root,pypi_requirements::wire_failure_rolls_back_already_written_files).e2e_bun_lockb::binary_shared_bundled_record_hosted_pin_is_managedneeds
patches-api.socket.dev, which the sandbox proxy blocks. None of themtouch yarn code.
scripts/yarn-classic-vex-matrix.sh 1.22.22: pass.scripts/yarn-berry-vex-matrix.sh 4.18.0: can't run here, because corepack can'tfetch yarn 4.18.0 behind the sandbox proxy. CI's
yarn-berryjob covers it./code-review high: two findings (names npm can't carry, such as zero-width
space,
?or@/x; versions with build metadata or numbers too large for npm)were fixed in
a3a6d63by reusing the existing npm validators. Thehelper-cycle cleanup was applied too. Not fixed: one extra JSON parse per
linked copy (negligible), and npm package-lock
file:entries readingnameliterally (vex/discover/npm.rs). That is a different lock format andreader, and it's left as a follow-up rather than widening this PR.
🤖 Generated with Claude Code
Note
Medium Risk
Changes Yarn copy identity and VEX/hosted warning behavior on a security-sensitive path; scope is limited to manifest parsing with broad new tests, plus a CI uv pin.
Overview
Fixes #1598 by tightening how Yarn reads
package.jsononportal:/link:/file:copies. Empty or invalid npmnamevalues and empty or non-semverversionvalues no longer produce a fake identity; they behave like a missing key, so hosted scan names the copy as possibly UNPATCHED and VEX withholds attribution instead of reporting a cleannot_affected.Core:
CopyRef::identityand sharedmanifest_namenow usepackage_name/package_version(registry name + npm semver validation, build metadata stripped).manifest_namelives incopy.rsso linked, directory, and tarball copies share the same rules.CI: Pipenv / pip legs pin uv 0.13.1 because 0.13.2 rejects Pipenv pylocks with
environments = [].Tests & docs: New hosted, on-disk, VEX discovery, and unit coverage;
ecosystems.mddocuments the rule.Reviewed by Cursor Bugbot for commit eb4de44. Configure here.
Generated by Claude Code