SocketDev / SocketDev/socket-cli

`socket pnpm install` fabricates alerts for packages not in the tree: pnpm v9 lockfile keys are truncated at the first underscore

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

まだ誰も着手していません。

主要言語
TypeScript
スター
317
フォーク
65
平均マージ
1時間 26分
マージ済み PR(30日)
30

説明

Summary

The pnpm shadow wrapper's lockfile scan mangles the name of any package whose name contains an underscore, submitting a purl for a different, unrelated package. In any pnpm-v9 project that depends on string_decoder (i.e. effectively every project, via readable-stream), socket pnpm install reports a High CVE for string@3.3.3 — a package that is not in the dependency tree at all — and exits 1.

Mechanism

stripPnpmPeerSuffix truncates a lockfile package key at the first ( or _:

function stripPnpmPeerSuffix(depPath) {
  const parenIndex = depPath.indexOf('(');
  const index = parenIndex === -1 ? depPath.indexOf('_') : parenIndex;
  return index === -1 ? depPath : depPath.slice(0, index);
}

The _ case is the pnpm lockfile v5 peer-suffix convention (/foo/1.0.0_bar@2.0.0). In lockfile v9, package keys are plain name@version, where _ is an ordinary legal character in npm package names. So extractPurlsFromPnpmLockfile maps:

Lockfile key (v9) Submitted purl
string_decoder@1.3.0 pkg:npm/string (versionless, wrong package)
evp_bytestokey@1.0.3 pkg:npm/evp
@types/babel__core@7.20.5 pkg:npm/@types/babel

The batch purl endpoint resolves the versionless pkg:npm/string to the real (unrelated) string package, whose latest version 3.3.3 carries a High CVE — which the wrapper's default filter treats as fatal, regardless of org policy. The other two mangled names happen not to resolve to alerting packages, which is why only string@3.3.3 surfaces.

Reproduction

mkdir repro && cd repro
npm init -y > /dev/null
printf 'lockfileVersion: "9.0"\npackages:\n  string_decoder@1.3.0:\n    resolution: {integrity: sha512-zOgAKMkjXbleOl9U5k7DBVdNwCRJW8ANhbJpEbriDmqu3nrOJPVHHqAmU7hBVBkoGuZbSpUnGdgOSg74RSPikw==}\nsnapshots:\n  string_decoder@1.3.0:\n    dependencies:\n      safe-buffer: 5.2.1\n' > pnpm-lock.yaml
SOCKET_CLI_DEBUG=1 DEBUG='*' socket pnpm install 2>&1 | grep -A5 purls
# → purls include 'pkg:npm/string' (no version), and the run fails on string@3.3.3's High CVE

(Alternatively: any real pnpm-v9 project with string_decoder in its lockfile reproduces it — we hit it in a 1,500-package workspace.)

Versions

Observed identical in @socketsecurity/cli@1.1.85, socket@1.1.143, and socket@1.1.155 (latest as of 2026-08-08): dist/utils.js stripPnpmPeerSuffix, reached via extractPurlsFromPnpmLockfilegetAlertsMapFromPnpmLockfile in dist/shadow-pnpm-bin2.js's install path.

Suggested fix

Only apply the _ truncation to v5-style dep paths (those beginning with / and using /name/version shape), or key the suffix-stripping on the lockfile's lockfileVersion. For v9 name@version keys, peer suffixes only ever appear in parentheses.

Impact

  • socket pnpm install fails spuriously (exit 1) for effectively any pnpm-v9 tree containing an underscore-named package that maps onto an alerting package name.
  • The submitted purl set silently omits the real packages (string_decoder, evp_bytestokey, @types/babel__* are never actually checked).

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

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

調査の方向性

示されている pnpm v9 の lockfile で問題を再現し、dist/utils.js の stripPnpmPeerSuffix と、dist/shadow-pnpm-bin2.js にある extractPurlsFromPnpmLockfile および getAlertsMapFromPnpmLockfile を介したその使用箇所を調査してください。完了条件は、アンダースコアを含む名前のパッケージが送信された purls 内で完全な名前とバージョンを保持し、該当する lockfile 形式では peer suffix が引き続き処理され、再現時に無関係な string alert が報告されなくなることです。

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

評価

技術スタック
typescript
領域
cli, security
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
66/100

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

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