piscina: `ThreadPool.options` 内のプロトタイプ汚染の脆弱性により、`execArgv`、`loadBalancer`、`env` などを介してリモートコード実行が可能になる。
### 概要
`ThreadPool.options` 内のプロトタイプ汚染の脆弱性により、`Object.prototype` を汚染できる攻撃者は、Piscina のワーカー スレッド内で任意のコードを実行したり、タスクスケジューリング中に任意の関数を呼び出したり、ワーカーに環境変数を注入したりすることができる。根本的な原因は、`ThreadPool.options` が通常のオブジェクトとして作成され、`Object.prototype` を継承しているため、`kDefaultOptions` に明示的なデフォルト値が設定されていないオプションは、プロトタイプチェーンを介して設定可能であることにある。
### 詳細
`src/index.ts` 内の `ThreadPool` コンストラクタでは、解決されたオプションオブジェクトが通常のオブジェクトとして構築される:
```ts
this.options = { ...kDefaultOptions, ...options, filename, maxQueue: 0 }
```
このオブジェクトが `Object.prototype` をプロトタイプとして持つため、オブジェクト自身のプロパティではないプロパティや、`kDefaultOptions` に存在しないプロパティへのアクセスは、`Object.prototype` にフォールバックする。これにより、プロトタイプ汚染の脆弱性(例えば、アプリケーション内の別の場所にある脆弱な `merge()` または `JSON.parse` の処理など)によって、`execArgv`、`env`、`loadBalancer`、`argv`、`workerData`、`resourceLimits`、`niceIncrement`、`closeTimeout`、`recordTiming`、`stricterFIFO`、`workerHistogram`、および `trackUnmanagedFds` などの値が注入される可能性がある。
最も深刻な脆弱性は `execArgv` であり、これは `new Worker(..., { execArgv })` に直接渡される。攻撃者は、`Object.prototype.execArgv = ['--require', '/tmp/attacker.js']` のように設定することで、すべてのワーカーが起動時に攻撃者が制御するモジュールをプリロードして実行させることができる。
この問題は、**GHSA-x9g3-xrwr-cwfg / CVE-2026-55388**(「Prototype Pollution Gadget → inherited options.filename を経由した RCE」)の修正を生き残りました。そのアドバイザリーでは、`Piscina` コンストラクタの `filename` の読み込みと、`run()` の `filename`/`name` の読み込みが強化されましたが、`ThreadPool.options` 自体は null プロトタイプで作成されていませんでした。そのため、`kDefaultOptions` に明示的なデフォルト値がないオプションに対しては、同じ種類の攻撃が依然として可能です。
### PoC (概念実証)
```js
import { resolve } from 'node:path'
import Piscina from 'piscina'
Object.prototype.execArgv = ['--require', '/tmp/attacker.js']
const pool = new Piscina({
filename: resolve(import.meta.dirname, 'worker.js'),
minThreads: 1,
maxThreads: 1,
})
await pool.run(1)
```
`/tmp/attacker.js` が、起動時にワーカー内で実行されます。`execArgv`、`loadBalancer`、および `env` のベクトルを含む完全な再現リポジトリは、https://github.com/Fcmam5/piscina-pp-poc で入手できます。
### 影響
- **リモートコード実行**: `execArgv` を経由 (任意の `--require` モジュールが、ワーカーの起動時にすべてのワーカーにプリロードされる)。
- **メインスレッドでの任意のコード実行**: `loadBalancer` を経由。これは、タスクのスケジューリング中に呼び出される攻撃者によって提供される関数です。
- **環境/CLI オプションの注入**: `env` を経由。これは、各ワーカーコンストラクタに渡されます。
- **サービス拒否 / 予期しない動作**: `workerData`、`resourceLimits`、`niceIncrement`、`closeTimeout`、`recordTiming` など、他のアクセス可能なオプションを介して発生する可能性があります。
`Object.prototype` が汚染される可能性があるアプリケーション (プロトタイプ汚染の脆弱性を持つ依存関係を介して) で Piscina を使用している場合は、影響を受ける可能性があります。
影響を受けるパッケージ:
- npm (JavaScript) piscina: 影響を受けるバージョン >= 5.0.0, < 5.3.2、5.3.2 で修正済み
- npm (JavaScript) piscina: 影響を受けるバージョン < 4.9.4、4.9.4 で修正済み
- npm (JavaScript) piscina: 影響を受けるバージョン >= 6.0.0-rc.1, < 6.0.0-rc.5、6.0.0-rc.5 で修正済み