Modern Frontend CVEs

対象CVE: CVE-2026-50143

[解説] Apify MCP ServerのURLAuthority Injection脆弱性 (GHSA-6gr2-qh89-hxwm) とAPIFY_TOKEN漏洩

Apify MCPサーバーライブラリ`@apify/actors-mcp-server`の脆弱性により、巧妙に細工されたActorを呼び出すことで、ユーザーのApify APIトークンが攻撃者のサーバーに漏洩する可能性があります。本記事では、このServer-Side Request Forgery (SSRF) のメカニズムと対策について、日本のフロントエンドエンジニア向けに解説します。

はじめに: Apify MCP Serverの深刻な脆弱性

いつもお世話になっております。フロントエンド開発者の皆様、日々のコード作成お疲れ様です。今回は、Apifyプラットフォームのコンポーネントの一つであるMCP(Model Context Protocol)サーバーライブラリ`@apify/actors-mcp-server`に発見された深刻な脆弱性 (GHSA-6gr2-qh89-hxwm / CVE-2026-50143) について解説します。この脆弱性は、URL authority injectionを利用したServer-Side Request Forgery (SSRF) に分類され、Apify APIトークンが攻撃者のサーバーへ漏洩する恐れがあります。CVSSベーススコアは8.1 (High) と評価されており、非常に高いリスクを伴います。

直接フロントエンドコードに影響するものではありませんが、Node.js環境で動作するサーバーサイドのライブラリに関する脆弱性であり、ビルドツールやCI/CDパイプライン、バックエンドAPIなど、フロントエンド開発者が間接的に関わる可能性のある領域で類似の問題が起こりうるため、そのメカニズムを理解することは非常に重要です。

脆弱性の概要:なぜAPIFY_TOKENが漏洩するのか?

問題は、`@apify/actors-mcp-server`がActorのスタンバイURLを構築する際に、信頼されたベースURLと、攻撃者が制御可能な`webServerMcpPath`の値を安全ではない方法で連結していたことにあります。

具体的には、Apify APIから取得されるActor定義内の`webServerMcpPath`フィールドが、十分に検証されることなくURLの一部として使用されます。攻撃者がこの`webServerMcpPath`に「`@attacker.example/mcp`」のような細工された値を設定した悪意のあるActorを公開すると、MCPクライアントは最終的なURLを全く異なるホスト(`attacker.example`)に解決してしまいます。

さらに深刻なのは、MCPクライアントがこの外部ホストへの接続に対しても、被害者の`Authorization: Bearer <APIFY_TOKEN>`ヘッダーを無条件に付与して送信してしまう点です。結果として、被害者のApify APIトークンは攻撃者のサーバーにそのまま exfiltrate(抜き取られ)てしまいます。

技術的な詳細:URLパーサーの落とし穴

脆弱性のあるコードは`src/mcp/actors.ts:44`にあります。

```ts return `${standbyUrl}${mcpServerPath}`; ```

`mcpServerPath`は、`webServerMcpPath`フィールドから取得され、トリムやカンマ区切りでの分割は行われますが、以下の重要な検証が欠けていました。

例えば、`webServerMcpPath`が`@attacker.example/mcp`に設定されると、連結されたURLは次のようになります。

``` https://real-actor-id.apify.actor@attacker.example/mcp ```

ここでNode.js(およびブラウザ、RFC 3986、WHATWG URL標準)のWHATWG URLパーサーの挙動が重要になります。URLにおいて`@`より前の部分は「userinfo」(ユーザー名やパスワード)として扱われ、その後に続く部分がホスト名として解析されます。上記の例では、`real-actor-id.apify.actor`がuserinfoとなり、`attacker.example`がホスト名として認識されてしまいます。これにより、意図しない外部ホストへリクエストが送信されることになります。

実際にNode.jsのREPLで確認できます。

```bash node -e "const u=new URL('https://ABC.apify.actor@127.0.0.1:31337/mcp'); console.log(u.hostname, u.username)" # Output: 127.0.0.1 ABC.apify.actor ```

この細工されたURLは`connectMCPClient()`関数に渡されます。この関数は、被害者のApify APIトークンをBearer認証情報として、以下のコードのように無条件にリクエストヘッダーに付与します。

```ts // src/mcp/client.ts:94 — SSEClientTransport requestInit authorization: `Bearer ${token}`, // src/mcp/client.ts:103 — SSE fetch callback headers.set('authorization', `Bearer ${token}`); // src/mcp/client.ts:124 — StreamableHTTPClientTransport requestInit authorization: `Bearer ${token}`, ```

URLの構築から外部HTTPリクエストが送信されるまでの間に、オリジンチェックが全く行われないため、攻撃者のサーバーにAPIトークンが漏洩してしまうのです。

影響とリスク:フロントエンド開発者への示唆

この脆弱性の影響を受けるのは、Apify APIトークンを設定しており(環境変数`APIFY_TOKEN`、サーバーオプション、または`_meta.apifyToken`経由)、かつ攻撃者が制御するActorに対して`call-actor`、`fetch-actor-details`、またはその他のactor-mcpタイプツールを呼び出すよう誘導されたユーザーです。被害者のApify APIトークンが攻撃者のサーバーに秘密裏に漏洩します。Apify APIトークンは、被害者のApifyアカウントへのフルアクセス権を付与するため、Actorの実行・管理、保存データへのアクセス、さらにはコンピューティング料金の発生など、多大な損害をもたらす可能性があります。

この攻撃は、被害者側に特別な権限やコード実行は不要で、Apifyプラットフォーム上の悪意あるActor定義だけで成立します。

フロントエンド開発者の皆様にとって、この脆弱性は以下の点で学ぶべき示唆があります。

対策と推奨事項

この脆弱性に対する推奨される修正は、以下のようになります。

```diff --- a/src/mcp/actors.ts +++ b/src/mcp/actors.ts export async function getActorMCPServerURL(realActorId: string, mcpServerPath: string): Promise<string> { const standbyUrl = await getActorStandbyURL(realActorId, standbyBaseUrl); - return `${standbyUrl}${mcpServerPath}`; + const url = new URL(mcpServerPath, `${standbyUrl}/`); + if (url.origin !== standbyUrl) { + throw new Error('Actor MCP server path must resolve under the Actor standby URL'); + } + url.username = ''; + url.password = ''; + return url.toString(); } ```

この修正では、`URL`コンストラクタを利用して`mcpServerPath`を正しく解析し、`url.origin`が`standbyUrl`と一致するかどうかを厳密に検証しています。また、ユーザー情報部分(`url.username`, `url.password`)を意図的にクリアすることで、userinfo injectionを防止しています。

**フロントエンド開発者への推奨事項:**

まとめ

今回のApify MCP Serverの脆弱性は、URLの扱いや依存ライブラリのセキュリティ対策の重要性を改めて浮き彫りにしました。直接フロントエンドコードに影響するケースは少ないかもしれませんが、URLの解析挙動や文字列連結によるセキュリティリスクは、あらゆるWeb開発において共通の課題です。

安全なコードを書くためには、OSやブラウザ、ランタイムが提供するAPIの挙動を深く理解し、外部からの入力は常に「信頼できないデータ」として扱う心構えが重要です。日頃からセキュリティ意識を高め、堅牢なシステム構築を目指しましょう。

← ブログ一覧に戻る