Caputchin
Caputchin を理解する

Caputchin がゲームをどうサンドボックス化するか

Caputchin のゲームは、あなたの訪問者のブラウザで、あなたのページで走るサードパーティのコードです。マーケットプレイスから来ようと、あなた自身がホストしようと、Caputchin はそれを 既定で信頼されないもの として扱い、いくつかの独立した隔離の層で包むので、バグのある、あるいは敵対的なゲームは、レンダリングし、遊び、結果を報告できますが、ほかには何にも到達できません。あなたのページにも、あなたの訪問者のデータにも、ネットワークにもです。

このページは、すべての手立て、それぞれがなぜ存在するか、そしてその全体が、あなた自身のサイトに加える CSP とどう相互作用するかを説明します。

一行での脅威モデル

ゲームは、サードパーティが供給する任意の JavaScript(そしておそらく WebAssembly)を走らせます。したがって隔離の目標は:ゲームは計算と描画ができ、結果をウィジェットに渡し戻せるが、自身のフレームの外側の何も読んだり影響したりできない。 以下のすべての層はその 1 つの目標に仕え、それらは多層防御で、どの単一の層も完璧だと信頼されません。

層 1:不透明オリジンのサンドボックス化された iframe

すべてのゲームは、ウィジェットが意図的に最小限の sandbox 属性で作る <iframe> の中で走ります。付与される 唯一の トークンは allow-scripts です。ゲームは JavaScript で、走らなければならないからです。ほかのすべては差し控えられ、最も重要な省略は allow-same-origin です。

allow-same-origin がないと、ブラウザはフレームに一意の null オリジン を与えます。その 1 つの事実が、荷重を支える境界です:

  • ゲームはあなたのページの DOM、クッキー、localStorage、または Caputchin のセッションを読めません。あなたのものとは異質な、使い捨てのオリジンに封じられています。
  • フレームはまた、あなたのトップウィンドウをナビゲートしたり、ポップアップを開いたり、フォームを送信したり、ネイティブのダイアログを出したりも決してできない(それらの能力はすべて Caputchin が付与しないサンドボックストークンです)ので、ゲームからあなたのページへ戻るパスがありません。

allow-same-origin なしの allow-scripts の組み合わせが要点そのものです。ブラウザはゲームのコードを実行しますが、フレームを、あなたのものに何も触れられない異質なオリジンとして扱います。Caputchin はゲームのフレームに allow-same-origin を決して加えません。(結果として、ゲームがウィジェットにポストするすべてのメッセージはオリジン "null" から届き、ウィジェットのチャネルのチェックはそれを期待します。null でないオリジンは、それ自体が設定ミスのサンドボックスを示します。)

層 2:フレームのドキュメントは取得されず、インラインで作られる

ウィジェットは iframe をリモートのページに向けません。フレームの HTML ドキュメント全体を インラインでsrcdoc 経由で)構築し、それを null オリジンのフレームに渡します。そのドキュメントは小さいです。厳格な CSP の meta タグ(次の層)、小さな Caputchin ランタイムのブートストラップ、そしてゲームのバンドルを読み込む 1 つの <script> タグです。

これは両方の配信パスで同じ仕組みで、バンドルの URL だけが違います:

ゲームのソースインラインドキュメントのバンドル URL
マーケットプレイス(プラットフォームが解決)Caputchin がマウント時に解決した、固定された完全性ハッシュ付きのバンドル URL。
セルフホスト(あなたの game-srcあなたが供給した URL。

ドキュメントはゲームではなくウィジェットによって作られるので、ゲームは CSP、ランタイム、フレームの構造を決して制御せず、読み込まれた後に自身のバンドルがすることだけを制御します。

層 3:マーケットプレイスのゲームの Subresource Integrity

Caputchin はマーケットプレイスのゲームを提供するとき、バンドルを不変のバージョンに固定し、その暗号ハッシュ(SHA-384)を記録します。バンドルを読み込む <script> タグは、そのハッシュを crossorigin="anonymous" 付きの integrity 属性として運ぶので、固定されたものと 1 バイトでも違えば、ブラウザ自身 がバンドルの実行を拒みます。侵害された CDN は違うコードを差し替えられません。読み込みはフェイルクローズします。

セルフホストのゲームには、プラットフォームが主張するハッシュがありません(あなたが自分のバイトの信頼の根です)ので、integrity 属性はそのパスでは単に省かれます。マーケットプレイスのゲームの 結果 がどうサーバーで独立に再導出されるか、完全性とは別の保証については、リプレイ契約 を参照してください。

層 4:厳格なインライン Content-Security-Policy

インラインドキュメントはきつい Content-Security-Policy を運びます。フレームがすでに null オリジンでサンドボックス化されているにもかかわらず、CSP は読み込まれたコードができることをさらに制約します。既定ですべてを拒否し、最小限だけを再付与します:

ディレクティブなぜ
default-src'none'下で明示的に許可されないすべてを拒否。
script-srcCaputchin 自身のインラインランタイムのハッシュ + ゲームバンドルのオリジン + 'wasm-unsafe-eval'Caputchin の正確なブートストラップ('unsafe-inline' ではなく sha256- ハッシュで固定)とゲーム自身のバンドルだけを走らせる。'wasm-unsafe-eval' は、完全な 'unsafe-eval' を付与せずに WASM エンジンがコンパイルできるようにする。
connect-src'none'持ち出し防止のディレクティブ。 ゲームはどこへも fetchXHRWebSocket を開く、ビーコンができません。ネットワークの送出は一切なし。
img-srcdata:(加えて、下記のスキンアセットのオリジン)スプライトはインライン、または許可されたアセットのホストから。
media-srcdata:(加えて、下記のスキンアセットのオリジン)音声/動画はインライン、または許可されたアセットのホストから。
font-srcdata:インラインのフォントのみ。
style-src'unsafe-inline'ゲームはインラインのスタイルを設定する。外部のスタイルシートはなし。(スタイルは、スクリプトやネットワークのようにはデータを持ち出せません。)

正味の効果:ゲームは走り、レンダリングし、SDK のブリッジを通じて結果を報告し、ほかには何にも、特にネットワークには到達できません。この CSP は Caputchin が設定し、あなたが設定するものではありません。ゲームがどれだけ閉じ込められているかを正確に理解できるよう、ここに挙げています。

顧客の設定がフレームの CSP を広げる唯一の場所

スキンは、画像や音声のフィールドを、あなた自身の CDN の絶対 URL に向けられます(スキン を参照)。それらのアセットがロックダウンされたフレームの中で読み込まれるよう、Caputchin は それらの正確なアセットのオリジンだけ をフレームの img-src / media-src に加え、ほかのどこにも加えません。script-srcconnect-src は決して広げられないので、許可されたアセットのオリジンでさえ、コードを読み込んだりネットワークのチャネルを開いたりに使えません。これが、設定された値がフレームのポリシーに影響する、単一の狭い方法で、それでもアセットだけです。

層 5:一方向の結果チャネル

ゲームはあなたのページへの呼び出せる面を持ちません。外への唯一の道は SDK のブリッジです。ゲームは、その不透明な結果(そのトレース)を、あなたのオリジンに住むウィジェットへ postMessage する単一のメソッドを呼びます。ウィジェットが Caputchin の API と話すものです。ゲームは決してしません(できません。connect-src'none' です)。なので信頼のパスは ゲーム → ウィジェット → あなたのバックエンド で、各ホップは結果を前へ渡すだけで、ゲームに後ろへの到達を決して付与しません。

あなた自身のページに設定する CSP

上の層は ゲームからあなたとあなたの訪問者を 守ります。あなた自身のページの Content-Security-Policy は、別の、補完的な制御です。それは あらゆるものからあなたのページを 守り、Caputchin は厳格なものの下で走るよう設計されています。Caputchin を埋め込むために CSP を緩める必要はありません。ウィジェットが正当に使う少数のオリジンを許可 すればよいのです。

最小限、ウィジェットは次を要します:

ディレクティブ許可なぜ
script-srcウィジェットのスクリプトを読み込むオリジン、加えて 'unsafe-eval'<caputchin-widget> / <caputchin-game> を定義する <script>、あなたが選んだ CDN(jsDelivr、あなた自身のホスト、または caputchin.com)。'unsafe-eval'計測 のチャレンジを走らせます。計測がオンの間は必須で、キーの セキュリティ ページで計測をオフにすれば落とせます。
connect-srchttps://caputchin.comウィジェットは、検証を用意して確認するために Caputchin の API を呼びます。ウィジェットを別の API ホストに向けるなら、代わりにそれを許可してください。
frame-srchttps://caputchin.comゲームの iframe を統べます。フレームはインラインの srcdoc ドキュメントを使うので、ブラウザはあなたの frame-src をそれに適用します。なのでここで Caputchin のオリジンを許可してください。
worker-srcblob:proof-of-work のソルバーは、blob: URL から作られた Web Worker の中で完全に走り、メインスレッドのフォールバックがないので、これは必須です。worker-src を省くと、ブラウザは child-src、それから default-src にフォールバックし、default-src 'self' だけでは blob: を許可しません。

任意で script-src'wasm-unsafe-eval' を加えてください。それは proof-of-work のソルバーを高速な WebAssembly として走らせます。必須ではありません。なしでも、ソルバーはより遅い純粋な JavaScript の実装(なお Worker の中)にフォールバックします。

ページの CSP でゲーム自身のバンドルのオリジン(jsDelivr、ゲームの CDN、あなたの game-src のホスト)を許可する必要は ありません。そのバンドルは、上で述べたフレーム自身の CSP の下で、サンドボックス化されたフレームの中で 読み込まれ、あなたのページのポリシーの下ではありません。あなたのページは Caputchin をフレームに収めるだけで、Caputchin が中で走るものを閉じ込めます。

Caputchin の要素があなたの CSP の下で黙って読み込みに失敗したら、あなたのブラウザのコンソールがブロックされたディレクティブを名指します。それが名指すオリジンかキーワードをそのディレクティブに加えてください。厳格に始め、コンソールが求めるものちょうどを開いてください。'unsafe-inline' は決して要りません。worker には blob:worker-src)が要り、計測がオンの間は script-src'unsafe-eval' が要ります。'unsafe-eval' の要件は、キーの セキュリティ ページで計測をオフにすれば消えます。'wasm-unsafe-eval' は任意です(proof-of-work のソルバーを速くします。さもなければ同じ Worker の中で JavaScript としてより遅く走ります)。

なぜこれほど多くの層か

各層は、それ自体で意味のある境界でしょう。一緒だと、1 つの失敗が破れではないことを意味します。null オリジンだけですでにゲームをあなたのデータから壁で隔て、CSP だけですでにネットワークの送出を殺し、完全性だけですでに正確なバイトを固定します。Caputchin はそのすべてを走らせます。信頼されないサードパーティのコードは、まさに多層防御が元を取る場所だからです。

あわせて読む

このページの内容