Firebase Hosting

Firebase HostingでHTTPヘッダーを良い感じにする

2021年03月27日

Gatsbyのドキュメントにあるfirebase.jsonの構成例では、キャッシュまわりの設定しかされていません。きちんと設定をしないとWebPageTestでのセキュリティの評価が低くなります。

035 DeskTop

現代のWebページはいくつかのHTTPヘッダーで、ブラウザの特定の挙動を制御してセキュリティを強化しています。WebPageTestのセキュリティ評価の部分をクリックすると、詳細なテストの結果が出てきます。

036 DeskTop

検索したところStackOverflowに「Firebase Hostingのセキュリティヘッダーこれ設定しておけば大丈夫」というような記事もみられたのですが、後学のためにもひとつひとつヘッダーの意味を見ていきましょう。

ヘッダーを見ていく

X-Content-Type-Options

ブラウザ側が勝手にMIMEタイプをファイルの中身から推測する(MIMEスニッフィング)のを避けるための設定です。普通は実行できないようなファイルに実行できるコードを仕込まれたりするような事故を防げます。

値はnosniffにしておきます。

X-Frame-Options

ページをiframeobjectの中に表示させなくできます。これでクリックジャッキングを防ぐことに繋がります。

とりあえずこのブログの中身がどこかに埋め込まれることはないはずなので、値はDENYに。

Content-Security-Policy(CSP)

これは少し複雑。XSSを防ぐためにページ内の画像などをどこから読み込むか制限をかけたり、HTTPSを使うことを強制したりすることができる。

これにはまず自分のWebサイトがどこから画像やフォント、スクリプトなどの要素を読んでいるのか知る必要があります。WebPageTestのウォーターフォール図を見るのが簡単でしょうか。

waterfall

パフォーマンスのためにスタイルシートやフォントといった外部から読まれがちなものもすべてlon.sagisawa.meの中でセルフホストする方針をとっており、画像だけContentfulのCDN(実体はAmazon CloudFront)から配信されています。ポリシーはこんな感じになるでしょう。

Content-Security-Policy: default-src 'self' images.ctfassets.net

……ただしこの設定、Gatsbyで採用した場合は問題が発生します。GatsbyはHTMLの中にスクリプトを埋め込むのですが、CSPが設定されている場合デフォルトではインラインのスクリプトやスタイルは無視されるようになってしまいます。Gatsby側でもCSPに対応するための議論は行われていますが、ひとまずはCSPは設定しない方向でいくことにします。

X-XSS-Protection

これは古いブラウザ向けのヘッダーのようで、現在の主要なWebブラウザー(Firefox, Chromium系, Safari)では代わりにCSPを指定することが推奨されているようです。ということで放置します。

設定する

Gatsbyのドキュメント通りに設定しているのであれば、firebase.json内に全ファイルに対するキャッシュまわりの設定が入っているはずです。そこにセキュリティ設定を追記します。

{
    "hosting": {
      "public": "public",
      "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
      "headers": [
        {
          "source": "**/*",
          "headers": [
            {
              "key": "cache-control",
              "value": "public, max-age=0, must-revalidate"
            },
            {
              "key": "x-content-type-options",
              "value": "nosniff"
            },
            {
              "key": "x-frame-options",
              "value": "DENY"
            }
          ]
        },
...

このブログはログイン機能などは付いていないのでこのような設定にあまり意味はないのですが、今後そのようなサイトを構築するようになれば重要になってくる……はず。

Screenshot 2021-03-27 15.19.44