安全に eval
前々から「script要素に permission 属性があるといいなあ」と思ってるのだけどそれは置いといて。
「404 Blog Not Found - スーパpre記法で実行可能なJavaScriptを」のようにページ作成者が任意の JavaScript をページ閲覧者に実行させたいという欲求はあるのだけれど、それはつまりページ閲覧者の(そのドメインにおける) Cookie 情報や、そのページの DOM 操作をページ作成者に委ねるということになります。script要素を自由に書けるようにすると、要求に対して権限が大き過ぎるんですよね。
そこで提案されてるのが上記リンクの「スーパpre記法で〜」で、「表示されているソースコードをページ閲覧者の意思でのみ実行できる」というもの。おそらく最も大きな脅威が「閲覧者が知らない(何もしない)間に情報を盗まれる」事だと思うので、それが解決される良いアイデアだと思いました。が、以下の問題があるように思います。
- CSSで別のソースを上に重ねて表示させることで、表示されてるコードと実行コードを別にできるのではないか?
- コードが読めない人でも実行できる。
後者を"自己責任"とするのは技術者としてあまりに優しくない態度だと思うので解決方法を考えました*1。
解決案(サービス側)
- 何の Cookie も保存しない別ドメインを用意する
- JavaScriptコードを受け取って、それを実行するボタンだけの HTML を返す CGI を用意する
ボタンクリックで上の CGI をiframe(display:none)で表示
これで(alert でブラクラとか別ページに飛ばすとかできるけれども)、元のページと実行ページとでドメインが異なることになりますから Cookie やページ内容(「ようこそXXさん」とか)を盗まれたり、ページを改竄されたりはしないはずです。
追記
やばい。情報は盗まれないけど DOS の踏み台になっちゃう実装だった。
追記
認証無しで script をアップロードできるようなものだから問題アリか(他所から POST された時に責任の所在がわかりにくくなる)。やっぱりこれは無しで。
解決案(クライアント側)
クライアント側といっても Opera9 だけですが。
Opera9 では data スキームが別ドメイン扱いになる*2ので、それを利用します。
(function(){ function evalInSandbox(text) { var iframe=document.createElement('iframe'); iframe.src=[ 'data:text\/html;charset=utf-8,', '<html>', '<script type="text\/javascript">', 'try{', text, '}catch(e){alert(e)}', '<\/script>', '<\/html>' ].join(''); iframe.style.display='none'; document.body.appendChild(iframe); setTimeout(function(){ document.body.removeChild(iframe) },1000); } alert(document.cookie); // 普通にクッキー表示 evalInSandbox('alert(document.cookie)'); // 空(dataスキームのクッキー) evalInSandbox('alert(window.parent.document.cookie)'); // Security error. // !! Firefox では表示できます !! })()
これを「山岸めも - 「スーパー pre 記法で実行可能な JavaScript を」user JavaScriptで」に組み込めばより安全になると思いました。
- -
参考
http://blog.livedoor.jp/dankogai/archives/50824976.html
http://d.hatena.ne.jp/ykzts/20070507/1178544767
evalInSandbox の(というかこのエントリ全体の)元ネタ。Japanize のソースを眺めていて知りました。
http://developer.mozilla.org/ja/docs/Components.utils.evalInSandbox
GreaseMonkey で使えるかと思ったらダメでした。Firefox でなにかいい方法があれば教えてください。