ポンコツエンジニアのごじゃっぺ開発日記。

いろいろポンコツだけど、気にするな。エンジニアの日々の開発などの記録を残していきます。 自動で収入を得られるサービスやシステムを作ることが目標!!

クロスオリジンのiframeでのalert()やconfirm()やpromptが使えなくなった問題【GAS】

Google Apps Script(以下、GAS)で、ウェブアプリで公開しつつ、表示されたHTML上のScript内でwindow.prompt()を使用して、文字列の入力を取得していました。

実行環境のブラウザはchromeを使っていたのですが、ある日から急に動かなくなったので、それの原因と解決方法を紹介したいと思います。

動かなかったスクリプト

いろいろ省略して、大事なところだけ書くと、以下のような感じのコードを使用していました。

gsファイル

function doGet() {
  var template = 'index';
  return HtmlService.createTemplateFromFile(template).evaluate();
}

index.htmlファイル

<!DOCTYPE html>
<html>
    <head>
       <base target="_top">
   </head>
    <body>
        <script>
           var text = window.prompt('文字を入力してください')
           // textをごにょごにょする
       </script>
    </body>
</html>

これが動かなくなった

今までは、文字入力のためのポップアップがブラウザの機能で表示されて、文字入力ができたのですが、急にできなくなりました。

原因

chromeのconsoleを見てみると、window.prompt()を呼んでいるところで、以下のようなログが出力されていました。

A different origin subframe tried to create a JavaScript dialog. This is no longer allowed and was blocked. See https://www.chromestatus.com/feature/5148698084376576 for more details.

f:id:ponkotsu0605:20210801171719p:plain

Google翻訳を適用すると、

別のオリジンサブフレームがJavaScriptダイアログを作成しようとしました。これは許可されなくなり、ブロックされました。詳細については、https://www.chromestatus.com/feature/5148698084376576を参照してください。

とのことです。クロスオリジンでjavascriptのダイアログを作成しようとする行為は許可されなくなっただと?

とりあえず、https://www.chromestatus.com/feature/5148698084376576のURLを見てみれば良いということですね。

Feature: Remove alert(), confirm(), and prompt for cross origin iframes

www.chromestatus.com

このChrome Platform Statusの記事のタイトルからもわかるように、クロスオリジンでのiframesからalert()やconfirm()やpromptが無効になったっぽいですね。

ここに書いてある内容を読んでみると、

  • iframeなどで別のサイトを表示して、その中でalertやwindow.promptなどでメッセージを表示させても、実際にユーザからしたら開いているページが表示しているメッセージと勘違いしてしまう
  • これが原因でなりすましが発生している
  • なりすまし軽減のために、別のサイトからメッセージを表示させていることを表示させようとも考えたが、UIが混乱して複雑になってしまったり、わかりにくかったりするのでそれはやめた
  • そもそもクロスオリジンのiframe内でjavascriptのダイアログってほぼ使われてないなら削除しましょうよ、という提案があった

みたいなことが書いてあるように読めました。たしかに、iframeからwindow.promptを利用したなりすましとか詐欺サイトがありそうですし、ユーザからは区別ができないですね。

In total, around 0.009% of page loads would be affected by the removal. We believe that core functionality will not be severely degraded, since the ability for users to disable JS prompts means sites already can’t rely on JS dialogs to always be displayed.

と書いているので、ページ全体の0.009%くらいの影響しかないということなのでしょうか?

Iframe'd origins that enroll in the origin trial will be allowed to show alert(), confirm() and prompt() dialogs even if embedded in a different origin site.

ということで、iframe内のalert(), confirm(), prompt()を使えないようなトライアルをしてみている。

developer.chrome.com

f:id:ponkotsu0605:20210801173433p:plain

対象のバージョンはchrome 92から適用されているみたいです。chrome 96(2021年12月15日)までトライアルと書いていますが、おそらく問題なければそのまま適用されてままかもしれませんね。

こちらのサイトに登録すればダイアログが表示されるみたいです?

chrome 92から適用なので、2021年7月20日くらいから反映されているはずです。

原因のまとめ

ということで、なりすまし対策で使えなくなったみたいです。セキュリティを考えると、こういうことも必要になってきますね。

解決策

さて、今回の場合は、window.promptで文字入力を受け付けたい処理を書きたかったのです。ではどうやって回避しましょうか。

GASのウェブアプリケーションとして公開した場合、HTMLはiframe内で表示されてしまうので、iframeは回避できなそうです。

ちなみに、setSandboxMode()でNATIVEやEMULATEDを指定すれば回避できたりするのかもと思いましたが、

The NATIVE and EMULATED modes were deprecated on October 13, 2015 and both are now sunset. Only IFRAME mode is now supported.

と書いているので、iframeしか選択できないみたいです。(というか、この機能を使ったことがなかったので、そもそもこれで回避できるかも不明)

developers.google.com

GASからはdoGet()やdoPost()を利用してHTMLを呼んでいるので、Browser.msgBox()なども利用できません(使ってみたけどエラーになった)

chromeの今回適用されたオプションを無効化することで回避もできるかもしれませんが、一時的な回避策になりそうで、そのうち無効化されそうだったので、恒久対応にはならないかなと判断して却下。

実施したこと

では、どういうことをしたのか?jQuery UIやVuetifyに置き換えましょうというサイトも見つけました。*1

今回は、inputタグのtype=textでシンプルなテキスト入力の入力フォームを作成して、jQueryを利用して、$('input').val()のように呼んであげることで、ユーザの文字入力を実現しました。

UIも変わってしまうので、大きな変更になってしまうので、参考にならないケースもあるかもしれないのですが、今回の自分のケースでは問題なかったので、このような回避策を取りました。

さいごに

セキュリティ対策は必須なことなので、今回の変更は仕方ないことではあると思います。これによってたくさんの人が詐欺に遭わないのであれば、仕方ない。

これからもこのようなアップデートにより、既存のjavascriptコードが動かなくなる可能性はあると思うので、たくさんの人が利用しているGoogle Chromeのリリースノートはちゃんと見ていかなきゃですね。

お問い合わせプライバシーポリシー制作物