iframe内でゲームが動かない:sandbox属性と許可の読み方
遊びをつくる執筆にClaudeを使用しています。

iframeにゲームを埋め込んだとき、見た目は表示されているのにボタンが反応しない、音が出ない、スコアが保存されない——そういった「動いているようで動いていない」状態の原因の多くは、sandbox属性による制限です。 sandbox属性は、埋め込んだコンテンツに対して「何を許可するか」を明示的に指定するHTMLの仕組みです。属性が付いているだけで、指定がなければほぼすべての操作が封じられます。ゲームのコードそのものに問題がなくても、埋め込む側のHTMLが適切な許可を与えていなければ動作しません。 この記事では、sandbox属性の読み方・書き方を軸に、よくある症状ごとの原因と修正手順を整理します。
sandbox属性が「無指定」と「空文字」で意味が変わる理由
まず前提として、sandbox属性には三つの状態があります。
- 属性自体がない:制限なし。埋め込んだページはほぼ自由に動作できます。
- sandbox=""(空文字):最も厳しい制限。スクリプト・フォーム送信・ポップアップ・ポインタロックなど、ほぼすべてが禁止されます。
- sandbox="allow-scripts allow-forms ...":許可リストを明示。書いたトークンだけが解禁されます。
埋め込み先のHTMLに <iframe src="game.html" sandbox></iframe> と書いた場合、sandbox は値のない属性として扱われ、空文字と同等の最大制限が適用されます。「sandboxと書いておけば安全側に倒せる」という感覚で追加したコードが、ゲームを完全に止めていることがよくあります。
症状から原因トークンを特定する
スクリプトが一切動かない
JavaScriptが実行されない場合は allow-scripts が欠けています。これが最も基本的なトークンで、これがなければCanvasの描画もイベント処理も動きません。
<!-- 修正前 -->
<iframe src="game.html" sandbox></iframe>
<!-- 修正後:スクリプトだけ許可 -->
<iframe src="game.html" sandbox="allow-scripts"></iframe>ただし、allow-scripts を付けても allow-same-origin を付けない場合、iframeのコンテンツはオリジン情報を持たない「null origin」として扱われます。これは意図的な設計で、同一ドメイン上に埋め込まれたコンテンツが親ページのCookieやlocalStorageに触れるのを防ぎます。
ローカルストレージ・IndexedDBが読み書きできない
allow-scripts だけを許可してスクリプトが動いても、localStorage.setItem() や IndexedDB の書き込みでエラーが出る場合があります。これは allow-same-origin がないことでオリジンが null になっているためです。
allow-same-origin を追加すると、iframeは親ページと同じオリジンとして扱われ、ストレージにアクセスできるようになります。ただし、このトークンを allow-scripts と同時に使うと、iframeのスクリプトが親ページのCookieやDOMにアクセスできる可能性が生まれます。信頼できる自分のコンテンツを埋め込む場合に限って使うべきトークンです。
フォームが送信できない・OAuth・外部ログインが機能しない
スコア送信やログイン処理にフォームやPOSTリクエストを使っている場合、allow-forms がなければ送信はブロックされます。また、外部の認証プロバイダにリダイレクトするタイプのログインは allow-popups や allow-top-navigation も必要になることがあります。
ポインタロック・フルスクリーンが効かない
3Dゲームや一部のアクションゲームで使う requestPointerLock() や requestFullscreen() は、allow-pointer-lock や allow-same-origin がないと拒否されます。ブラウザの開発者ツールのコンソールに Permissions Policy または Feature Policy 関連のエラーが出ていれば、このケースを疑ってください。
音声・動画が自動再生されない
sandbox とは別の話になりますが、混同されやすいので触れます。音が出ない原因の大半は、sandbox ではなくブラウザの自動再生ポリシーです。ユーザー操作なしに AudioContext を開始しようとすると、多くのブラウザで停止されます。iframeに allow-autoplay というトークンはなく、これは Permissions-Policy ヘッダーやiframeの allow 属性(sandbox とは別属性)で制御されます。音が出ない場合はまずコンソールの NotAllowedError を確認してください。
安全性を保ちながら許可を最小限にする考え方
sandbox を外してしまえばすぐ動く場合が多いですが、それは必ずしも正しい解決ではありません。第三者のゲームを埋め込む場合や、公開プラットフォームに投稿されたコンテンツを表示する場合は、sandbox による制限が利用者の保護になります。
許可の追加は、症状を一つ確認するたびに一つずつ追加して動作を確かめる方法が確実です。一度に全トークンを並べると、どれが効いているのかわからなくなります。
よく使われる組み合わせを整理すると次のようになります。
- JavaScriptゲームの最低限動作、推奨トークンの組み合わせ:allow-scripts
- localStorageも使う自作ゲーム、推奨トークンの組み合わせ:allow-scripts allow-same-origin
- フォーム送信あり、推奨トークンの組み合わせ:allow-scripts allow-same-origin allow-forms
- 第三者コンテンツ(ストレージ不要)、推奨トークンの組み合わせ:allow-scriptsのみ(allow-same-originは付けない)
allow-same-origin は利便性が高い分、リスクも高いトークンです。自分が管理するコンテンツ以外には付けないことを原則にしてください。
開発者ツールで原因を素早く絞り込む手順
- ブラウザの開発者ツールを開き、Consoleタブを確認します。Blocked by sandbox や SecurityError というメッセージが出ていれば、sandbox制限が原因です。
- Networkタブでリクエストがブロックされていないか見ます。フォーム送信やFetch/XHRがキャンセルされていれば allow-forms や allow-same-origin の不足を疑います。
- iframeの要素をElementsタブで選択し、現在のsandbox属性の値を確認します。意図せず空文字になっていないかをここでチェックします。
- エラーメッセージに Permissions Policy と書いてある場合は、sandbox ではなく allow 属性またはHTTPレスポンスヘッダーの問題です。sandbox の修正では解決しません。
コンソールのエラーコピーで検索すると、ブラウザのドキュメントに詳細が載っています。「ゲームが動かない」という状態から「どのAPIがどの理由でブロックされているか」まで絞り込めれば、修正はほぼ一行で済みます。
次の行動
まずブラウザの開発者ツールのConsoleを開き、sandbox や SecurityError のメッセージがないか確認してください。エラーが見つかったら、この記事の症状別セクションと照らし合わせてトークンを一つずつ追加してみてください。自作のゲームをアソバースに投稿して公開する場合、埋め込み側の制御はプラットフォームが担うため、ゲーム内部のAPI呼び出しとコンソールエラーに集中するのが効率的です。

