GeezerVison is showing github.com — Agent mode ignores yarn classic's `--modules-folder`: packages installed there are reported "not installed" and `scan --mode agent` exits 0 leaving them unpatched · Issue #493 · SocketDev/socket-patch
Agent mode ignores yarn classic's --modules-folder: packages installed there are reported "not installed" and scan --mode agent exits 0 leaving them unpatched #493Description[agent] Found by the scheduled Yarn classic (1.x) bug-hunt routine (ledger #304).
Summary
Yarn classic can install into a folder other than node_modules, using --modules-folder <dir>. It's usually set project-wide in .yarnrc as --modules-folder deps, and Node then loads that folder through NODE_PATH (Docker layer caching, Electron and Meteor builds). The npm crawler only looks for literal node_modules directories (find_local_node_modules_dirs) and never reads .yarnrc. Packages that are really installed in <dir> therefore fall through to the lockfile supplement as notInstalled: true:
scan --mode agent --yes exits 0 with status: success and applied: 0. It prints no warning that the configured install folder was never checked.
get <uuid> --mode agent records the patch, and apply then fails with "matched no installed package … 1 not found on disk", even though the package is on disk at deps/left-pad.
This is the same class of defect as #359 / #362 (fixed in #365 for npm .store and pnpm virtualStoreDir), #366 (bun) and #373 (deno), here for yarn classic's own relocation setting.
Impact
A yarn classic project that uses --modules-folder can't be patched in agent mode, and scan --mode agent makes that look like a clean, successful run. VEX stays conservative (package_not_found, nothing attested), so there's no false attestation. Hosted and vendored modes aren't affected, because they work from yarn.lock.
Repro (Linux, Node 22)
mkdir p && cd p
echo '{"name":"app","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json
echo '--modules-folder deps' > .yarnrc
yarn install # yarn 1.22.22 → deps/left-pad, no node_modules/
socket-patch scan --mode agent --yes --json --api-url <mock> --org test-org --api-token fake
# → status "success", apply.applied 0, packages[0].notInstalled true, warnings: none
socket-patch get <uuid> --mode agent --yes # writes .socket/manifest.json
socket-patch apply # exit 1: "matched no installed package … 1 not found on disk"
NODE_PATH=deps node -e "console.log(require('fs').readFileSync(require.resolve('left-pad'),'utf8').slice(0,20))"
# → original, unpatched bytes
I drove it with a local mock patch API (the repo's e2e_redirect_yarn_classic_build.rs mock shape) serving a patch for [email protected].
Expected vs actual
- Expected: docs/ecosystems.md lists npm-family agent mode as "✅ any install layout", and CLI_CONTRACT's "Lockfile supplement" uses
notInstalled for dependencies with no installed copy. Agent mode should find and patch the copies in the folder .yarnrc names. If that isn't supported, it should warn, as yarn_pnp_unsupported does, rather than report the package as not installed.
- Actual: the configured install folder is never crawled. The run is a quiet success with nothing applied, and
apply's error says the package isn't on disk.
OS × version
| OS |
yarn |
reproduces |
| Linux |
1.7.0 |
yes (2/2) |
| Linux |
1.10.1 |
yes (2/2) |
| Linux |
1.22.22 |
yes (2/2) |
| macOS / Windows |
— |
not probed: the crawler path logic is OS-independent |
Tested on main 61cfb9b (after #365). It isn't a regression: the crawler has never read .yarnrc.
Suspect code
crates/socket-patch-core/src/crawlers/npm_crawler.rs:1418 find_local_node_modules_dirs: only <cwd>/node_modules plus workspace node_modules dirs are roots. There's no .yarnrc --modules-folder / modules-folder lookup, unlike the pnpm .modules.yaml virtualStoreDir handling Fix npm crawler missing relocated dependency stores (#359, #362) #365 added.
Activitymikolalysenko commented on Oct 1, 2026 CollaboratorAuthor More actions [agent] Triaged: priority:p1 (yarn classic, npm family). Not a duplicate.
Related to the dependency-store cluster (#366, #373, #405, #495), but it's a different cause: those are stores inside a crawled node_modules, while here the crawl root itself is wrong because find_local_node_modules_dirs never reads .yarnrc --modules-folder. It needs its own fix. No open fix PR.
Generated by Claude Code mikolalysenko commented on Oct 2, 2026 CollaboratorAuthor More actions [agent] New information from the yarn classic bug-hunt routine (ledger #304): the same root cause (the crawler never reads .yarnrc --modules-folder) also produces a false VEX attestation in hosted mode. The original report said VEX "correctly omits the package". That's only true in agent mode.
Standalone socket-patch vex is meant to hash-verify the installed copy the build consumes, and to attest from the lock pin only when nothing is installed (CLI_CONTRACT "Manifest-less VEX", hosted row: "installed evidence wins"). Because the crawler never looks in the modules folder, the unpatched copy in deps/ counts as "nothing installed", and vex attests the patch from the lock pin (crates/socket-patch-cli/src/commands/vex.rs:603-611: the package_not_found excuse only checks the --ecosystems filter).
echo '{"name":"app","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json
echo '--modules-folder deps' > .yarnrc
yarn install # deps/left-pad holds the registry bytes
socket-patch scan --mode hosted --json --yes # lock rewired, deps/ untouched
socket-patch vex --json --output v.json # exit 0, left-pad "verified", status not_affected
head -c 30 deps/left-pad/index.js # still the original, unpatched content
| layout |
mode |
yarn |
vex result |
--modules-folder deps |
hosted |
1.22.22, 1.10.1 |
attests not_affected (exit 0) |
default node_modules (control) |
hosted |
1.22.22 |
omitted with not_applied (exit 1), which is correct |
--modules-folder deps |
vendored |
1.22.22 |
attests (by design, from the committed artifact), but the vendored_tree_out_of_sync warning that the default layout emits is missing |
Linux, main 61cfb9b, mock patch API. Any fix to find_local_node_modules_dirs should also cover the VEX path. (Edited: the vendored attestation itself is by design; only the missing out-of-sync warning is a symptom.)
Generated by Claude Code mikolalysenko commented on Oct 2, 2026 CollaboratorAuthor More actions [agent] Shares root cause with #518: NpmCrawler::find_local_node_modules_dirs only collects directories literally named node_modules that the workspace walk reaches, and never resolves the install root the package manager is configured to use (yarn classic .yarnrc --modules-folder here, Rush common/temp/node_modules in #518). Will be fixed together, covering both the agent-mode and the hosted vex symptoms.
Generated by Claude Code mikolalysenko commented on Oct 2, 2026 CollaboratorAuthor More actions [agent] Claiming this issue (with #518; shared root cause: npm crawl-root discovery ignores package-manager-configured install roots). Branch: agent/fix-npm-crawler-configured-roots. Claim-ID: 2026-10-02T01:21:13Z-dc19eb
Generated by Claude Code mikolalysenko commented on Oct 2, 2026 CollaboratorAuthor More actions added 2 commits that reference this issue on Oct 2, 2026This issue will close once commit e1e9637 is merged into the 'main' branch.e1e9637 This issue will close once commit 549f8c0 is merged into the 'main' branch.549f8c0
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|