このサイトを安全にした

単なる静的サイトなので別に脅威は無いが、診断サイトの指摘にかたはしから対応していった。もっとstrictにもできるが、過去の記事がちゃんと表示されていることを確認するのも面倒なのでマイルドな設定のみ変更している。たとえばFlashだとかSilverlightなんかは当然無効化してもよいが、いくつかのページでStyleSheetをインラインで指定しているし、Disqus(この記事の下にもあるコメント欄)を埋め込んでいるのでinlineのscriptを完全には無効化できなかった。(追記2022/01/17:Disqusを削除したので無効化できた)

そもそもこのブログにコメント欄が必要なのかというのも微妙なところではある。ほとんど書き込みのないコメント欄を設置することに意味があるのか。これまで一件も書き込みがなければ削除してもいいが、しかしそういうわけでもない。たまーにコメントをいただく。いままでのところ辛辣な内容もなく、政治的な内容に振れてもないからか荒れることもない。そしてコメントをもらうとうれしいのだ。SNSもやってないのにこの辺境のブログにいったいどうやったらたどりつけるのかわからないが、しかしどうやってか見に来ているひとがいるらしい(ナウルが流行っているのでたぶんそれだろう、というくらいはわかるが)。

この手のセキュリティ対策というのは簡単にHTMLタグを追加するだけ完了する項目はごく限られていて、HTTP Headersに追加しないとならない設定が多い。HSTSのようなメジャーな設定はCDNとして使っているCloudflareの標準機能で追加できるものだが、その他の新しい機能については自分で対応する必要がある。このブログはCloudflare Pagesをつかって静的サイトとして配信しているにすぎず、サーバーサイドのこまかな設定はできない。なのでCloudflare Workersでページのリクエストに対し動的にヘッダーを追加することにした。

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  const response = await fetch(request)
  const headers = new Headers(response.headers)
  headers.set("X-Frame-Options", "DENY")
  headers.set("Referrer-Policy", "no-referrer")
  headers.set("Permissions-Policy", "camera=(); microphone=(); interest-cohort=()")
  headers.set("Content-Security-Policy", [
    "default-src https: 'self'",
    "style-src https: 'self' 'unsafe-inline'",
    "script-src 'self' https://platform.twitter.com/ https://static.cloudflareinsights.com/",
    "object-src 'none'",
    "frame-ancestors 'none'",
    "base-uri 'none'",
    "form-action 'none'"
  ].join('; '))
  return new Response(response.body, {
    status: response.status,
    statusText: response.statusText,
    headers
  })
}

Cloudflare Workersは他のFaaSとは違い、世界各地のエッジサーバー上でプログラムが起動する。それも1ms以下で、だ。AWS Lambdaと比較しても猛烈に速いのでヘッダーを書き換えるみたいなライトな処理であればレイテンシを実感することはできない。Cloudflareの新しいサービスは、その多くが自社のCloudflare Workersをインフラとして構築されているという。今後なにか新しいサービスをつくるときはこちらを主体に使ってみよう。