Agent-mode npm apply, apply --check and vex skip a declared workspace member in a hidden directory (.github/actions/x, .config/tool), so its nested copy stays unpatched while VEX attests not_affected
维护者通常 1 天内回复
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 53/100
调研方向
Start with skipped_members_of and workspace_children in crates/socket-patch-core/src/crawlers/npm_crawler.rs, then read docs/ecosystems.md for the documented workspace behavior. Reproduce with the .github/actions/x workspace example and compare agent-mode scanning with the nested node_modules copy. Done when the declared hidden workspace member is crawled, or checks and VEX clearly flag the unpatched copy.
由索引模型根据 Issue 内容生成。
描述
[agent] Found by the scheduled npm bug-hunt routine (ledger #302).
Summary
#1627 made the agent-mode node_modules walk crawl a declared workspace member whose path crosses a SKIP_DIRS name (packages/build, vendor/lib). A declared member inside a hidden directory is still pruned. A common example is a JavaScript GitHub Action kept as an npm workspace at .github/actions/<name>, matched by "workspaces": [".github/actions/*"]. Another is an explicit ".config/tool" entry. npm 7+ treats these as workspace members and installs each member's unhoistable dependencies into <member>/node_modules from the root lock, so the copy there is live.
skipped_members_of (crates/socket-patch-core/src/crawlers/npm_crawler.rs:109) walks the patterns with a walkable filter that rejects every name starting with . (line 121). It also only adds a member when its path crosses a SKIP_DIRS name (line 183). The main walk's workspace_children drops hidden dirs too (line 3476). The result:
scan --mode agentpatches every other copy of the samename@version, skips the hidden member's copy, and exits 0.apply --checkreports "Patches are in sync".vexwrites anot_affectedstatement for the vulnerability, though npm runs the unpatched bytes from.github/actions/x/node_modules/left-pad.
If the hidden member holds the only copy, scan --mode agent prints [skip] pkg:npm/[email protected] (not installed; run your package manager's install first …) and exits 0. The package is installed.
Impact
A false VEX attestation, the same class as #1627: a scanner consuming the VEX suppresses a vulnerability in code that is installed and executed (for example by the Action at runtime). Nothing in the output warns about it.
Repro (npm 10.9.4, Node 22.22.0, Linux)
The patch API is a local mock. Any patch for [email protected] shows it; a hand-staged .socket/manifest.json works the same way.
mkdir -p proj/.github/actions/x proj/packages/y && cd proj
echo '{"name":"root","version":"1.0.0","private":true,"workspaces":["packages/*",".github/actions/*"],"dependencies":{"left-pad":"1.3.0"}}' > package.json
echo '{"name":"x","version":"1.0.0","dependencies":{"left-pad":"1.2.0"}}' > .github/actions/x/package.json
echo '{"name":"y","version":"1.0.0","dependencies":{"left-pad":"1.2.0"}}' > packages/y/package.json
npm install
# lock: node_modules/left-pad (1.3.0), packages/y/node_modules/left-pad and
# .github/actions/x/node_modules/left-pad (both 1.2.0)
socket-patch scan --mode agent --yes --api-url <mock> --org test-org --api-token fake
head -c 20 packages/y/node_modules/left-pad/index.js # /* SOCKET-PATCHED */
head -c 20 .github/actions/x/node_modules/left-pad/index.js # /* This program is f <- unpatched
socket-patch apply --check … # "Patches are in sync (1 patch checked)", exit 0
socket-patch vex … -O v.json # 1 statement, status not_affected, exit 0
Expected vs actual
docs/ecosystems.md, "npm: which node_modules trees are crawled": the walk skips hidden directories and build dirs, "except that a workspace member the root package.json workspaces field declares … still has its own node_modules crawled. npm, yarn and Bun install a member's unhoistable dependencies there from the root lock." The usage docs say agent VEX attests "Installed patched files, checked against the manifest's hashes".
- Expected: the declared member
.github/actions/xhas itsnode_modulescrawled and patched. At the least,apply --check/vexmust not report the patch as in sync or attestnot_affectedwhile that copy is unpatched. - Actual: the copy is never seen. apply,
--checkandvexall succeed.
Matrix (Linux, Node 22.22.0)
| socket-patch | npm | member path | result |
|---|---|---|---|
main ecd4924 |
8.19.4 | .github/actions/x (glob) |
fail |
main ecd4924 |
10.9.4 | .github/actions/x (glob) |
fail (2/2) |
main ecd4924 |
10.9.4 | .config/tool (explicit pattern) |
fail |
main ecd4924 |
12.2.1 | .github/actions/x (glob) |
fail |
main ecd4924 |
10.9.4 | tools/build/x (control, #1627 shape) |
pass |
| v5.0.1 | 10.9.4 | .github/actions/x |
fail |
This isn't a regression: v5.0.1 does the same. macOS and Windows are untested; the cause is platform-independent. Hosted and vendored modes are unaffected, because the pin is lock-driven and npm ci installs the patched tarball into the hidden member too. The walk is shared, so yarn and Bun workspaces probably behave the same (not verified).
Suspect code
crates/socket-patch-core/src/crawlers/npm_crawler.rs:121:walkableinskipped_members_ofrejects hidden names, including the literal prefix of a pattern such as.github/actions/*.crates/socket-patch-core/src/crawlers/npm_crawler.rs:183: members are only added when the path crosses aSKIP_DIRSname, so a hidden segment would need the same treatment.crates/socket-patch-core/src/crawlers/npm_crawler.rs:3476:workspace_childrenprunes hidden dirs.
No probe runs: probe branches are blocked for this routine (see the ledger).
- 主要语言
- Rust
- 星标
- 8
- 派生
- 2
- 平均合并
- 19 小时 24 分钟
- 30 天内合并 PR
- 669
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
SocketDev/socket-patch 的其他 Issue
-
agent:triaged arch-audit priority:p3 refactor
难度 2/5 1-3 小时 新手友好度 83/100
SocketDev/socket-patch#1860 ·
维护者通常 1 天内回复
-
agent:triaged arch-audit priority:p3 refactor
难度 2/5 1-3 小时 新手友好度 78/100
SocketDev/socket-patch#1838 ·
维护者通常 1 天内回复
-
Vendored npm rollback / remove / vendor --revert on a lockfileVersion 2 lock fail after any `npm install`, yet half-revert the lock: `packages` goes back to the registry while the legacy mirror keeps the patched integrity, and npm 6 then fails EINTEGRITY可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭bug bughunt pm:npm
难度 4/5 3-5 天 新手友好度 35/100
SocketDev/socket-patch#1937 ·
维护者通常 1 天内回复
-
arch-audit refactor
难度 4/5 3-5 天 新手友好度 22/100
SocketDev/socket-patch#1935 ·
维护者通常 1 天内回复
-
arch-audit bug
难度 3/5 半天 新手友好度 55/100
SocketDev/socket-patch#1934 ·
维护者通常 1 天内回复
查看 SocketDev/socket-patch 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 62/100
calcit-lang/calcit#2538 ·
维护者通常 1 天内回复
-
Remove the em dashes from the skill smart-account reference可能已有人在做 @Vamsi-2581 今天认领。 未关闭agent-ready area: docs documentation good first issue
难度 2/5 1-3 小时 新手友好度 74/100
Soneso/stellar-agent-wallet#541 · 2 条评论 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 78/100
bovinemagnet/AdocFoundry#279 ·
维护者通常 1 天内回复
-
help wanted
难度 1/5 半天 新手友好度 72/100
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 65/100
weihubeats/Miyo#132 · 1 条评论 ·
维护者通常 2 天内回复