Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Agent-mode npm apply, apply --check and vex skip a declared workspace member whose directory is named build, dist, vendor, tmp, temp or coverage, so its nested copy stays unpatched while VEX attests not_affected

オープン
#1,627 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@mikolalysenko がすでに取り組んでいます。

2026年10月17日 から。

  • #1628 @mikolalysenko による — オープン

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
48/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
node.js, rust
領域
cli, security

調査の方向性

Start with crates/socket-patch-core/src/crawlers/npm_crawler.rs, especially SKIP_DIRS and workspace_children near line 2965; compare with bun_workspace_pattern_members_sync near line 768 and read docs/ecosystems.md for the crawl contract. Reproduce with the packages/build workspace from the issue, then check apply, apply --check, and vex. Done means declared members in skipped-name directories are crawled and their installed copies are handled consistently by all three commands.

索引モデルが issue の本文から書いたものです。

説明

agent:claimed agent:triaged bug bughunt pm:npm priority:p1

[agent] Found by the scheduled npm bug-hunt routine (ledger #302).

Summary

The npm crawler's workspace walk prunes every directory named dist, build, coverage, tmp, temp, __pycache__ or vendor (SKIP_DIRS). It does this even when the root package.json workspaces field declares that directory as a member, and npm installs it from the root lock. When npm can't hoist a member's dependency (a version conflict with the root), npm installs it into <member>/node_modules/. A member at packages/build, packages/dist, tools/build or vendor/lib is common in real monorepos, and its nested copy is then never crawled. As a result:

  • apply patches the other copies and prints 1 of 1 targeted patch applied, 0 … not found on disk. The member's copy stays unpatched with no warning.
  • apply --check reports Patches are in sync.
  • vex attests not_affected / inline_mitigations_already_exist for the product.
  • At runtime, Node resolves the member's own unpatched copy (require.resolve('ms') from the member → <member>/node_modules/ms/index.js).

Impact

The tool reports a false security attestation (VEX not_affected) and a passing CI audit (apply --check), while a vulnerable copy that npm installed from the project's own lock runs in production code. Nothing warns about it.

Repro (Linux, npm 10.9.4 / Node 22; same on npm 8.19.4 and npm 12.2.1 / Node 24)

mkdir ws && cd ws && mkdir -p packages/app packages/build
echo '{"name":"root","version":"1.0.0","private":true,"workspaces":["packages/*"],"dependencies":{"ms":"2.1.3"}}' > package.json
echo '{"name":"app","version":"1.0.0","dependencies":{"ms":"2.0.0"}}'   > packages/app/package.json
echo '{"name":"build","version":"1.0.0","dependencies":{"ms":"2.0.0"}}' > packages/build/package.json
npm install
# -> node_modules/[email protected], packages/app/node_modules/[email protected], packages/build/node_modules/[email protected]
# Stage a .socket/manifest.json + blobs for pkg:npm/[email protected] that appends a marker to index.js
# (a hand-staged agent manifest; any real [email protected] patch behaves the same)
socket-patch apply
#   Summary: 1 of 1 targeted patch applied, 0 already patched, 0 not found on disk
grep -c socket-patched packages/app/node_modules/ms/index.js    # 1  (patched)
grep -c socket-patched packages/build/node_modules/ms/index.js  # 0  (UNPATCHED)
socket-patch apply --check          # Patches are in sync (1 patch checked).  exit 0
socket-patch vex --product pkg:npm/[email protected] -O vex.json   # statement: not_affected
(cd packages/build && node -p "require.resolve('ms')")       # …/packages/build/node_modules/ms/index.js (unpatched)

If you rename packages/build to packages/lib, both copies are patched (control).

Expected vs actual

  • Expected: CLI_CONTRACT (apply --check) says "each installed copy hashes to the record's afterHash", and drift is exit 1. docs/ecosystems.md ("npm: which node_modules trees are crawled") says the scan collects "every node_modules found in the directories below it (workspace members, nested projects)". The name-based prune is meant for build-output / cache dirs ("well-known non-workspace dirs" in the code comment), not for a directory that workspaces declares and that npm installs into from the root lock. At a minimum, the crawler should never let vex attest not_affected while such a copy is unpatched.
  • Actual: declared members whose directory names are in SKIP_DIRS are skipped silently by apply, apply --check, agent scan and vex.

Matrix (agent mode, main 657fce2)

OS npm / Node member dir apply patches member copy apply --check vex
Linux 10.9.4 / 22.22.0 packages/build no in sync (wrong) not_affected (wrong)
Linux 10.9.4 / 22.22.0 packages/dist no in sync (wrong) not_affected (wrong)
Linux 10.9.4 / 22.22.0 vendor/lib no in sync (wrong) not_affected (wrong)
Linux 10.9.4 / 22.22.0 tools/build no in sync (wrong) not_affected (wrong)
Linux 8.19.4 / 22.22.0 packages/build no in sync (wrong) not_affected (wrong)
Linux 12.2.1 / 24.22.0 packages/build no in sync (wrong) not_affected (wrong)
Linux 10.9.4 packages/lib (control) yes in sync not_affected (correct)

Release v5.0.1 (npm @socketsecurity/socket-patch) behaves the same, so this is not a regression since the last release. Not tested this run: hosted and vendored modes, which rewire from the lock rather than the crawl; macOS / Windows (probe branches are currently blocked for this routine, but the walk is OS-independent).

Suspect code

  • crates/socket-patch-core/src/crawlers/npm_crawler.rs:21 (SKIP_DIRS)
  • crates/socket-patch-core/src/crawlers/npm_crawler.rs:2965 (workspace_children, which applies SKIP_DIRS without consulting the root package.json workspaces globs; the crate already expands those globs for Bun in bun_workspace_pattern_members_sync, around line 768)

The crawler is shared by the other JS package managers, so pnpm / yarn / Bun workspaces with a member at such a path probably behave the same. This report is scoped to npm.

主要言語
Rust
スター
8
フォーク
1
平均マージ
16時間 39分
マージ済み PR(30日)
584

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

SocketDev/socket-patch のほかの issue

SocketDev/socket-patch の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。