Read My Blog With JavaScript

Michael Lynch

JavaScriptで私のブログを読めるようにしました

原文は Michael Lynch により に公開されました。 このブログを購読する

私のブログがクライアントサイドのJavaScriptで読めるようになりました。なぜそうしたいのかはよくわかりませんが、とにかく可能です。

たとえば、お気に入りのブログの最新記事一覧をブログロールとして自分のサイトに追加したいけれど、サーバーサイドで取得したくはない、という場合があるかもしれません。JavaScriptで私の最新5件の記事タイトルを表示したいなら、次のようなコードを書きます。

fetch("https://mtlynch.io/index.xml")
  .then((response) => response.text())
  .then((str) => new DOMParser().parseFromString(str, "application/xml"))
  .then((data) => {
    const articles = [...data.querySelectorAll("item")].map((item) => ({
      title: item.querySelector("title").textContent,
      date: new Date(item.querySelector("pubDate").textContent),
    }));

    // Sort articles by date, newest to oldest.
    articles.sort((a, b) => b.date - a.date);

    // Print the titles of the 5 most recent articles.
    articles.slice(0, 5).forEach((article) => console.log(article.title));
  });

上記のコードを実行すると、次のような出力が得られます。

Refactoring English: Month 10
Get xkcd Cartoons at 2x Resolution
List of 2x-resolution xkcd Cartoons
I Once Appeared in The Old New Thing
Refactoring English: Month 9

このアイデアは、LobstersでSimon Willisonが残した最近のコメントから得ました。

JavaScriptから自分のサイトを読めるようにするには

JavaScriptからのアクセスを可能にするために変更したのは、RSSフィードにCross-Origin Resource Sharing(CORS)のHTTPヘッダーを設定したことだけでした。通常、クライアントサイドのJavaScriptで他のサイトのコンテンツを読み取ることを妨げているのが同一オリジンポリシーです。

同一オリジンポリシーとは、各サイト(オリジン)は自身のドメインに紐づくリソースしか読み取れないというルールです。たとえば、あなたがmtlynch.ioで私のブログを訪れていて、私のページ上のJavaScriptがchase.comからあなたの銀行残高を読み取ろうとしても、同一オリジンポリシーによってそのアクセスはブロックされます。

他のウェブサイトがJavaScript経由で私のブログを読めるようにするには、ブログのRSSフィードにCORSヘッダーを設定する必要がありました。このブログは現在Netlifyでホストしている静的サイトなので、Netlifyの設定ファイルを変更してRSSフィードのURLにCORSヘッダーを指定しました。

[[headers]]
  for = "/index.xml"
  [headers.values]
    Access-Control-Allow-Origin = "*"
    Access-Control-Allow-Methods = "GET, HEAD, OPTIONS"
    Access-Control-Allow-Headers = "Content-Type"

何が問題になりうるか

CORSはセキュリティ機構であり、インターネットに公開しているサイトのセキュリティ制限を緩めることには、常に慎重であるべきだと考えています。ただ、しばらくリスクについて検討した結果、私のケースでは実質的なリスクはないと判断しました。

攻撃者に秘密のデータを抜き取られる可能性は?

同一オリジンポリシーの目的は、ユーザーがサイトAに機密データを持っている場合、サイトAが明示的に許可しない限りサイトBがそのデータにアクセスできないようにすることです。

私のブログは機密情報を一切持たない静的サイトです。私がmtlynch.ioを訪れても、他の人が見るものとまったく同じものが表示されるだけです。したがって、たとえ攻撃者が私を騙してサードパーティのサイトで悪意のあるJavaScriptを実行させたとしても、そのコードが私のブログ上での権限を悪用することはありません。そもそも私自身、ここでは特別な権限を持っていないからです。

埋め込みコメントにはTalkYardを使っていて、そこでは私に管理者権限がありますが、RSSフィードのCORS設定はTalkYardには影響しません。

攻撃者にDDoS攻撃される可能性は?

当初は、攻撃者がCORS設定を悪用して私のサイトにDDoS攻撃を仕掛けるのではないかと考えました。もし攻撃者が何百万人もの人々をあるページに誘導し、裏側でJavaScriptが私のRSSフィードに絶えずリクエストを送るようにしたらどうなるだろう、と。

しかし、そうしたDDoS攻撃はすでに可能であることに気づきました。CORSが制御するのは、サードパーティのドメインがリクエストの結果を読み取れるかどうかだけで、そもそものリクエスト自体をブロックするわけではありません。CORSの設定にかかわらず、どのドメインも他のどのドメインに対してもGETやPOSTリクエストを送ることができます。

攻撃者にサイトを偽装される可能性は?

検討したもう一つの攻撃は、なりすましです。訪問者がevil.example.comにアクセスすると、そのサーバーがJavaScriptを返し、URLバーにはevil.example.comと表示されたまま、訪問者のブラウザ内で私のブログを再構築するというものです。

この攻撃は成立しうるものの、CORS設定の有無にかかわらず、私のブログを偽装するもっと簡単な方法があります。偽装者は私のブログへリクエストを転送するHTTPプロキシを立てるだけでも偽装できますし、単にサイトをスクレイピングして別の場所でホストすることも可能です。

なぜJavaScriptからブログを読めるようにしたのか

誰かに頼まれてRSSフィードでCORSを有効にしたわけではないので、これが実際に誰かの役に立つのかはわかりません。ただ、私はオープンなウェブが好きですし、他のサイトが私のサイトと相互運用できる面白い方法だと思ったので、やってみてもいいだろうと考えたのです。

もしこの変更をきっかけに私のRSSフィードを使って何か面白いことをしたら、ぜひ教えてください

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。

コメント