なぜサンドボックス認証が難しいのか
LLMベースのエージェント(OpenCode、Claude Codeなど)が普及するにつれ、外部API呼び出しを安全に処理する方法が重要になっています。特にサンドボックス内で実行されるコードは信頼できないため、APIトークンを直接注入する従来の方法はリスクが伴います。トークンが漏洩すると、攻撃者に悪用される可能性があります。
この記事では、Cloudflare Sandboxのoutbound Workers機能を利用して、エージェントが外部サービスを呼び出す際に**ゼロトラスト(Zero Trust)**の原則を適用する方法をステップバイステップで解説します。
従来の認証方式の課題
| 方式 | メリット | デメリット |
|---|---|---|
| APIトークン直接注入 | 実装が簡単 | トークン漏洩リスク、有効期限管理が煩雑 |
| OIDCワークロードアイデンティティ | 短期トークンでセキュリティ向上 | サービス統合が困難、独自トークン交換サーバーが必要 |
| カスタムプロキシ | 完全な柔軟性 | プロキシ構築・運用が複雑、パフォーマンス問題 |
理想的な認証メカニズムは、ゼロトラスト、シンプルさ、柔軟性、パフォーマンス、透過性をすべて満たす必要があります。outbound Workersがどのようにこれらの条件を満たすか見ていきましょう。

実践: outbound Workersでゼロトラスト認証を実装する
1. 基本: リクエストのログ記録とブロック
最もシンプルな例として、すべてのアウトバウンドHTTPリクエストをインターセプトし、GETのみ許可してそれ以外をブロックします。
class MySandboxedApp extends Sandbox {
static outbound = (req, env, ctx) => {
// GET以外のリクエストはすべてブロックしログを記録
if (req.method !== 'GET') {
console.log(`コンテナが ${req.method} リクエストを送信: ${req.url}`);
return new Response('許可されていません', { status: 405 });
}
// GETリクエストはそのまま転送
return fetch(req);
};
}
このプロキシはサンドボックスVMと同じマシン上で実行されるため、レイテンシはごくわずかです。Workersダッシュボードですべてのログを確認でき、可観測性も確保できます。
2. ゼロトラスト認証情報の注入
最も強力なユースケースは、シークレットトークンをサンドボックスに一切露出させずに外部サービスへ安全に渡すことです。
class OpenCodeInABox extends Sandbox {
static outboundByHost = {
"my-internal-vcs.dev": (request, env, ctx) => {
// リクエストヘッダーにシークレットトークンを追加
// サンドボックス内のコードはこのトークンを絶対に見られません!
const headersWithAuth = new Headers(request.headers);
headersWithAuth.set("x-auth-token", env.SECRET);
return fetch(request, { headers: headersWithAuth });
}
};
}
ここで重要なのは、env.SECRETがサンドボックスではなくoutbound Workerの環境変数としてのみ存在する点です。また、ctx.containerIdを利用してサンドボックスインスタンスごとに異なるトークンを注入することも可能です。
static outboundByHost = {
"my-internal-vcs.dev": async (request, env, ctx) => {
// KVは保存時・転送時に暗号化されています
const authKey = await env.KEYS.get(ctx.containerId);
const requestWithAuth = new Request(request);
requestWithAuth.headers.set("x-auth-token", authKey);
return fetch(requestWithAuth);
}
}
3. 動的ネットワーク制御
初期はnpmパッケージをダウンロードするためにGitHub、npmjs.orgへのアクセスを許可し、インストール完了後は即座にブロックするシナリオです。
class MySandboxedApp extends Sandbox {
static outboundHandlers = {
async allowHosts(req, env, { params }) {
const url = new URL(request.url);
if (params.allowedHostnames.includes(url.hostname)) {
return await fetch(newRequest);
} else {
return new Response(null, { status: 403 });
}
},
async noHttp(req) {
return new Response(null, { status: 403 });
}
};
}
async function setUpSandboxes(req, env) {
const sandbox = await env.SANDBOX.getByName(userId);
// 初期: GitHub, npmのみ許可
await sandbox.setOutboundHandler("allowHosts", {
allowedHostnames: ["github.com", "npmjs.org"]
});
await sandbox.gitClone(userRepoURL);
await sandbox.exec("npm install");
// インストール完了後、すべてのHTTPをブロック
await sandbox.setOutboundHandler("noHttp");
}
これにより、ネットワークが開放されている時間を最小限に抑え、攻撃対象領域を削減できます。
4. MITMプロキシによるHTTPSトラフィック制御
HTTPSリクエストも制御するにはTLS復号が必要です。Cloudflare Sandboxは各インスタンスごとに**一時認証局(CA)**を生成し、サンドボックス内部にインストールします。
export class MyContainer extends Container {
interceptHttps = true;
}
MyContainer.outbound = (req, env, ctx) => {
// すべてのHTTP(S)リクエストがこのフックを通過します
return fetch(req);
};
この方式は完全に透過的に動作します。サンドボックス内のアプリケーションはプロキシの存在を認識しません。
5. 発展: WorkerEntrypointを活用した細粒度制御
IP範囲やホスト名パターン(globマッチング)でリクエストをインターセプトできます。
export class MyWorker extends WorkerEntrypoint {
fetch() {
return new Response(this.ctx.props.message);
}
}
// コンテナ内部
this.ctx.container.start({ enableInternet: false });
const outboundWorker = this.ctx.exports.MyWorker({ props: { message: 'hello' } });
await this.ctx.container.interceptOutboundHttp('15.0.0.1:80', outboundWorker);
// 以降、15.0.0.1:80へのすべてのHTTPリクエストは "hello" を返します
// 動的に変更可能!既存の接続にも影響なし
const secondOutboundWorker = this.ctx.exports.MyWorker({ props: { message: 'switcheroo' } });
await this.ctx.container.interceptOutboundHttp('15.0.0.1:80', secondOutboundWorker);
// ホスト名、CIDR(IPv4/IPv6)もサポート
await this.ctx.container.interceptOutboundHttp('example.com', secondOutboundWorker);
await this.ctx.container.interceptOutboundHttp('*.example.com', secondOutboundWorker);
await this.ctx.container.interceptOutboundHttp('123.123.123.123/23', secondOutboundWorker);
すべてのプロキシはサンドボックスVMと同じマシン上でローカルに実行されるため、コンテナとWorker間の通信は「認証なし」でも安全です。

注意点と制限
- パフォーマンスオーバーヘッド: MITMプロキシを使用するとTLSハンドシェイクが追加で発生します。レイテンシに非常に敏感なアプリケーションでは注意が必要です。
- 証明書の信頼問題: サンドボックス内部にインストールされた一時CAはそのサンドボックスでのみ有効です。標準コンテナでは
sudo update-ca-certificatesなどで手動設定が必要になる場合があります。 - 複雑なポリシー:
outboundHandlersを複数定義すると管理の複雑さが増します。ポリシーをコードで管理するため、バージョン管理とテストが必須です。 - Cloudflareエコシステム依存: 現在この機能はCloudflare Workersエコシステム専用です。他のプラットフォームで同様の機能を実装するには、独自のプロキシサーバー(Envoy、Nginxなど)をVM内にデプロイする必要があるかもしれません。
次のステップ
- Cloudflare Sandbox公式ドキュメントでさらに多くの例を確認してください。
- OIDCとoutbound Workersを組み合わせたワークロードアイデンティティフェデレーションパターンを学習してみてください。
wrangler devを使用したローカル開発環境のセットアップ方法を習得すると、生産性が大幅に向上します。
![]()
まとめ
outbound Workersは、サンドボックス環境においてゼロトラスト、動的制御、透過性をすべて満たす強力な認証・ネットワーク制御ソリューションです。わずか数行のJavaScriptでAPIトークンを安全に注入し、動的にネットワークポリシーを変更し、すべてのトラフィックを監視できます。
特にLLMエージェントがますます多くの権限を必要とする現在、このアプローチは必須です。「信頼できないコード」に「最小権限」のみを付与するという原則をコードレベルで実現できます。
合わせて読みたい記事