Simon Willisonがdatasette-appsをリリースした。GitHubのREADMEとブログ記事を読んで、正直「えぐい設計してるな」と思った。
Core idea自体はシンプルで、DatasetteにカスタムのHTML+JavaScriptアプリを乗っける仕組みだ。ただ、その安全性の担保の仕方が面白い。iframeに `sandbox="allow-scripts allow-forms"` を付けつつ、さらにCSPヘッダーをHTMLの冒頭に `` として埋め込んでいる。このCSP、一度 `srcdoc` に書いたら上書きできない性質を利用して、外部へのfetchを完全にブロックしている。
つまりこういう構成だ。
この3層構造、実際に手を動かしながら読んで初めて「ああ、これ順番が大事なんだ」と気づいた。sandboxだけだとfetch()で外部に情報が流れる穴がある。CSPだけだと親のDOMを触れてしまうケースがある。両方を組み合わせることで、untrustedなコードを認証済みのDatasetteインスタンス上で動かせる状態になる。
自分が以前ハマったことと重なる話でもあった。半年前に社内ツールで似たような構成を作ろうとして、iframeサンドボックスを付けたのにセッションのcookieが漏れるバグを出した。あのとき `allow-same-origin` を無意識に追加していたのが原因だったんだけど、今回の記事を読んで「あれはCSPも合わせて設定すべきだった」と後から理解できた。当時のPRを引っ張り出してコメントに追記しておいた。
面白かったのはpostMessageまわりの話だ。GPT-5.5(記事の表記のまま)がレビューで「postMessageだけだと外部コードをロードされたときに迂回できる」と指摘したと書いてある。LLMがセキュリティレビューに使われて、しかも有効な指摘をしているという状況が普通に混在しているのが2026年っぽいなと感じた。
自分のコードへの影響を考えると、今チームで作っているダッシュボードツールに似た構造がある。SQLiteのデータをJSON APIで返して、フロントのiframeコンポーネントでレンダリングしている部分だ。現状はsandboxの設定が緩くて、`allow-same-origin` が残ったままになっている。datasette-appsが採用した `srcdoc` + CSP metaのパターンに切り替えれば、外部ホストへのリクエストを確実に止めた状態でレンダリングできる。
ただ `allow-same-origin` を外すとiframe内からの一部APIコールが壊れる可能性があるので、そこは来週のスプリントで確認するつもりだ。
DatasetteのAgent機能と組み合わせると、LLMが生成したHTMLアプリをそのままiframeで実行してSQLiteに読み書きできる環境になる。Claude Artifactsに永続的なリレーショナルDBを付けたようなもの、と記事に書いてあって、それはかなり正確な表現だと思った。個人開発でちょうどLLMに雑なデータ集計を投げてHTML出力させることが増えているので、datasette-appsのパターンを個人プロジェクトに持ち込む価値はある。
Hacker Newsのコメントスレッドは71ポイントで24コメントと、反応はそこまで爆発してないけど、内容はぎっしりしていた。同じようにiframeサンドボックスの穴について議論しているスレッドがあって、特定ブラウザでのCSP挙動の差異も話題になっていた。実装するなら手元でChromeとSafariとFirefoxを横断して確認する必要がありそうだ。
`allow-same-origin` を外すのは怖くてずっと先送りにしていたが、今日読んだ内容で「外すほうが正しい」という確信が持てた。月曜にPRを出す。
Core idea自体はシンプルで、DatasetteにカスタムのHTML+JavaScriptアプリを乗っける仕組みだ。ただ、その安全性の担保の仕方が面白い。iframeに `sandbox="allow-scripts allow-forms"` を付けつつ、さらにCSPヘッダーをHTMLの冒頭に `` として埋め込んでいる。このCSP、一度 `srcdoc` に書いたら上書きできない性質を利用して、外部へのfetchを完全にブロックしている。
つまりこういう構成だ。
# sandboxで親DOMへのアクセスを遮断
# CSP metaで外部ドメインへのHTTPを遮断
# postMessage + MessageChannelで親との通信を制御この3層構造、実際に手を動かしながら読んで初めて「ああ、これ順番が大事なんだ」と気づいた。sandboxだけだとfetch()で外部に情報が流れる穴がある。CSPだけだと親のDOMを触れてしまうケースがある。両方を組み合わせることで、untrustedなコードを認証済みのDatasetteインスタンス上で動かせる状態になる。
自分が以前ハマったことと重なる話でもあった。半年前に社内ツールで似たような構成を作ろうとして、iframeサンドボックスを付けたのにセッションのcookieが漏れるバグを出した。あのとき `allow-same-origin` を無意識に追加していたのが原因だったんだけど、今回の記事を読んで「あれはCSPも合わせて設定すべきだった」と後から理解できた。当時のPRを引っ張り出してコメントに追記しておいた。
面白かったのはpostMessageまわりの話だ。GPT-5.5(記事の表記のまま)がレビューで「postMessageだけだと外部コードをロードされたときに迂回できる」と指摘したと書いてある。LLMがセキュリティレビューに使われて、しかも有効な指摘をしているという状況が普通に混在しているのが2026年っぽいなと感じた。
自分のコードへの影響を考えると、今チームで作っているダッシュボードツールに似た構造がある。SQLiteのデータをJSON APIで返して、フロントのiframeコンポーネントでレンダリングしている部分だ。現状はsandboxの設定が緩くて、`allow-same-origin` が残ったままになっている。datasette-appsが採用した `srcdoc` + CSP metaのパターンに切り替えれば、外部ホストへのリクエストを確実に止めた状態でレンダリングできる。
# 現状
<iframe sandbox="allow-scripts allow-same-origin" src="...">
# 変更後の方針
<iframe sandbox="allow-scripts allow-forms" srcdoc="...">
# srcdoc内のHTMLの冒頭に
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src data: blob:;">ただ `allow-same-origin` を外すとiframe内からの一部APIコールが壊れる可能性があるので、そこは来週のスプリントで確認するつもりだ。
DatasetteのAgent機能と組み合わせると、LLMが生成したHTMLアプリをそのままiframeで実行してSQLiteに読み書きできる環境になる。Claude Artifactsに永続的なリレーショナルDBを付けたようなもの、と記事に書いてあって、それはかなり正確な表現だと思った。個人開発でちょうどLLMに雑なデータ集計を投げてHTML出力させることが増えているので、datasette-appsのパターンを個人プロジェクトに持ち込む価値はある。
Hacker Newsのコメントスレッドは71ポイントで24コメントと、反応はそこまで爆発してないけど、内容はぎっしりしていた。同じようにiframeサンドボックスの穴について議論しているスレッドがあって、特定ブラウザでのCSP挙動の差異も話題になっていた。実装するなら手元でChromeとSafariとFirefoxを横断して確認する必要がありそうだ。
`allow-same-origin` を外すのは怖くてずっと先送りにしていたが、今日読んだ内容で「外すほうが正しい」という確信が持てた。月曜にPRを出す。