安全確認のしくみ
Morphifexが受け取るのは、モデルが書いたコードです。それをそのまま画面で表示し、ゲームなら実際に動かします。だから、保存する前に中身を検査します。
なぜ検査するのか
モデルが出力するのはSVGとHTMLです。どちらもブラウザーがそのまま解釈して動かす形式で、書き方によっては通信もできますし、外部のファイルも読み込めます。モデルが悪意を持っているかどうかとは関係なく、学習した書き方をなぞった結果としてそういうコードが出てくることがあります。
Morphifexはオフラインで完結することを前提にした道具です。そこで、許可した書き方だけを通し、それ以外は保存も表示もしないという方針を取っています。検査に落ちたものは、黙って書き換えたりせず、理由を付けてモデルへ差し戻します。
SVGで通すもの
使ってよい要素をあらかじめ決めています。ここに無い要素が1つでも含まれていれば、そのSVGは通りません。
| 常に使える | svg / g / path / rect / circle / ellipse / line / polyline / polygon / text / tspan / defs / linearGradient / radialGradient / stop / clipPath / mask / pattern / title / desc |
|---|---|
| アニメーションONのときだけ | animate / animateTransform / animateMotion / set / mpath |
アニメーションをOFFにしているのに動きの要素が混ざっていた場合も、検証失敗として扱います。ぼかしなどのfilter系は許可リストに入っていないため通りません。描き直しを頼むときも、グラデーションと半透明の図形で代えるよう指示します。
SVGで弾くもの
script | SVGの中でJavaScriptを動かす要素。禁止です。 |
|---|---|
foreignObject | SVGの中へHTMLを差し込む要素。禁止です。 |
| イベント属性 | onloadやonclickなど、onで始まる属性はすべて禁止です。 |
| 外部URL・data URL | javascript:、data:、http:やhttps:で始まる参照を禁止します。外部画像も外部フォントも読み込めません。 |
href / src | 同じSVGの中を指す#始まり以外は禁止です。 |
@import | 外部スタイルの読み込みを禁止します。 |
| XML宣言 / DOCTYPE | どちらも禁止です。 |
通ったものだけが残る
検査を通ったSVGだけを保存し、書き出しの対象にします。最後にsharpで実際にPNGへ描き出せることまで確かめて、はじめて完成扱いです。
- モデルの出力からSVGを取り出す
前後の説明文やコードフェンスを取り除き、SVGの部分だけを切り出します。名前空間の宣言が無い場合だけ、保存前に一度補います。
- 許可リストと禁止パターンで検査する
上の表の条件に照らします。落ちた場合、違反の理由と許可されている要素を添えて、同じモデルへ描き直しを頼みます。
- それでも通らなければ保存しない
描き直しの回数には上限があります。イラストとアイコンは作成画面で選んだ追加やり直しの回数(0〜3回)、従来方式の安全訂正は最大2回です。使い切っても通らなかった候補は保存も書き出しもせず、最後に成功していた安全なSVGをそのまま残します。
4コマ漫画での扱い
4コマ漫画は台詞を描くので、textとtspanを使います。それ以外の条件は通常のSVGと同じで、script、イベント属性、foreignObject、外部URL、外部画像・外部フォント、data URL、アニメーションを拒否します。
加えて、コマの枠が検証済みの構成と同じ座標にあるか、構成で決めた台詞が同じ番号のコマに入っているかを照合します。一致した候補だけを完成として扱います。出力の上限は10,000トークンで、その範囲で閉じないSVGは保存しません。
レーティングを成人向けにしても、この条件は緩めません。未成年者を性的に扱う入力は、モデルへ送る前に拒否します。
Webゲームでの扱い
Webゲームは1つのHTMLファイルとして作ります。外部のファイルを一切読み込まない、自己完結した形が条件です。
必須にしていること
<!doctype html>から始まる、完結したHTML文書であること。headとbodyがあること。- ゲーム画面が
canvasかsvgであること。 - 動かすJavaScriptがHTMLの中に直接書かれていること。
大きさの上限
| HTML全体 | 512KiB(524,288バイト) |
|---|---|
| JavaScriptの合計 | 384KiB(393,216バイト) |
弾く書き方
- 要素:
iframe、frame、object、embed、base、form、link、audio、video、source。 - 外部参照:外部scriptの読み込み、外部URL、外部リンク。画像や音声は
data:以外から読み込めません。 - 通信:
fetch、XMLHttpRequest、WebSocket、EventSource、sendBeacon。 - コードの動的生成:
eval、Function、動的import、Worker。 - 外へのアクセス:
window.open、document.cookie、localStorageとsessionStorage、親画面(parent・top)の参照。
検査のときも、サーバーが生成コードを実行することはありません。動かさずに構文だけを確かめます。違反が見つかったコードは黙って削らず、理由と前回のHTMLを添えて、残っているやり直し回数の範囲で同じモデルへ直しを頼みます。
動かすときの囲い
できたゲームは、Morphifex本体の画面へ差し込みません。sandbox="allow-scripts"を付けたiframeの中だけで動かします。同一オリジン扱い、フォーム送信、ポップアップ、最上位ページの移動、ダウンロードの権限はどれも与えていません。
そのうえで、配信するHTMLと書き出すHTMLの両方に、次のCSP(コンテンツセキュリティポリシー=ブラウザーに読み込みを制限させる指定)を付けます。
| 既定 | default-src 'none'。指定のないものはすべて読み込めません。 |
|---|---|
| JavaScript / CSS | HTMLの中に直接書かれたものだけ。 |
| 画像 | data:とblob:のみ。 |
| 遮断 | 通信、フォント、音声・動画、frame、object、base、フォーム送信。 |
プレビューには、Morphifexが固定で用意した監視だけを追加します。エラーが起きた候補は正常として通知せず、修復へ回します。
この検査でカバーしていないこと
現在の検査は、文字列の照合を中心にした最低限のものです。厳密なXMLパーサーによる検証、URLやCSSの値の構文解析、要素数やパス長といった資源量の制限、攻撃入力を集めた回帰テストは、これからの課題として残しています。