零弐壱蜂

[HTML] rel="noopener"が必要だった過去と基本的に不要になった現状について

TL;DR

  • かつてtarget="_blank"のリンクはwindow.opener脆弱性が存在し、rel="noopener"で対策する必要があった
  • 2019年5月、WHATWG HTML仕様のPR #4330により更新され、現在は主要ブラウザ(Chrome 88+, Firefox 79+, Safari 12.1+)でtarget="_blank"に自動的にnoopenerの挙動が適用される
  • 最新ブラウザでは基本的にrel="noopener"の明示的な指定は不要になった
  • 古いブラウザのサポートが必要な特殊な環境では引き続き指定することを推奨

はじめに

target="_blank"属性は外部リンクを新しいタブで開く際に広く使用されている。以前はセキュリティリスクが存在し、rel="noopener"属性の追加が推奨されていた。

現在では主要ブラウザがこのセキュリティ対策を自動適用するため、明示的な指定は基本的に不要である。

window.opener脆弱性とは

target="_blank"でリンクが開かれたとき、新しいタブやウィンドウはデフォルトでwindow.openerプロパティを通じて元のページにアクセスできる。

window.openerとは、現在のウィンドウを開いた親ウィンドウへの参照を保持するJavaScriptプロパティである。通常のリンククリックではnullだが、target="_blank"で開かれた場合は元ページのwindowオブジェクトが設定される。これにより新しいページから元ページのDOM操作やナビゲーション制御が可能になる。

この仕組みは以下のセキュリティリスクを引き起こした:

タブナッピング(Tabnabbing)攻撃

悪意のあるリンク先はwindow.opener.locationを使用して、元のページを別のページ(フィッシングサイトなど)にリダイレクトできた。この攻撃手法は「タブナッピング」として知られ、2010年にセキュリティ研究者のAza Raskinによって報告された。

// 悪意のあるサイトでのタブナッピング攻撃例
if (window.opener) {
  // 元のタブを偽のログインページにリダイレクト
  window.opener.location = 'https://fake-banking-site.example/login';
}

この攻撃は特に危険で、ユーザーが新しいタブで作業中に元のタブが気付かれることなく悪意のあるサイト(偽の銀行ログインページなど)に変わってしまう。ユーザーが元のタブに戻ったとき、正規サイトだと思い込んでログイン情報を入力してしまう可能性がある。

パフォーマンスへの影響

セキュリティリスクに加え、window.openerの存在により新しいページと元のページが同じブラウザコンテキストで実行されるため、パフォーマンス低下の可能性も存在した。

rel="noopener"の導入

これらのリスクに対応するため、2014年ごろにrel="noopener"属性が提案され、ブラウザに実装された。この属性を使用すると、新しいタブではwindow.openernullに設定され、元のページを操作できなくなる。

<!-- 推奨される使用方法 -->
<a href="https://example.com" target="_blank" rel="noopener">Example Website</a>

rel="noreferrer"という属性も存在し、これはnoopenerと同様の効果に加え、HTTPリファラ(参照元情報)を送信しないようにする。

<!-- より強固なセキュリティ対策の例 -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">Example Website</a>

これらの属性の使用は、ウェブセキュリティのベストプラクティスとして広く推奨され、多くのセキュリティ検査ツールやLighthouseなどでもチェック項目となった。

ブラウザの進化と仕様変更

2018年ごろ、Safariがtarget="_blank"の挙動を変更し、自動的にnoopenerを適用する実験を開始した。その後2019年5月、WHATWG(Web Hypertext Application Technology Working Group)HTML仕様のPR #4330により更新され、target="_blank"を指定したリンクは自動的にrel="noopener"と同じ動作をするようになった。

各ブラウザの実装時期

仕様変更後、主要ブラウザは次のように実装した。

  • Safari 12.1(2019年3月)から実装
  • Firefox 79(2020年7月)から実装
  • Chrome 88(2021年1月)から実装
  • Microsoft Edge 88(2021年1月、Chromiumベース移行後)から実装

これにより、現在の主要ブラウザでは明示的にrel="noopener"を指定しなくても、target="_blank"のリンクは安全に動作する。

現在の状況と推奨される対応

現在のブラウザでの挙動

現在の状況をまとめる。

  • すべての主要ブラウザ(Chrome、Firefox、Safari、Edge)では、target="_blank"に自動的にnoopenerの挙動が適用される
  • 逆にwindow.openerを使いたい場合は、明示的にrel="opener"を指定する必要がある
  • HTTPリファラ情報を送信したくない場合は引き続きrel="noreferrer"を使用する必要がある

後方互換性の考慮

Internet Explorer(IE)は2022年6月15日にサポートが終了したため、現在では基本的に考慮不要である。ただし、非常に古いバージョンのブラウザサポートが必要な特殊環境では、引き続きrel="noopener"を指定することが推奨される。最新ブラウザでは冗長になるが、レガシー環境での後方互換性を確保する安全策である。

<!-- レガシー環境での安全な方法 -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">Example Website</a>

セキュリティツールとの関係

Lighthouseなどのセキュリティチェックツールでは、まだrel="noopener"rel="noreferrer"の使用を推奨している場合があるが、これは以下の理由による。

  1. 後方互換性の保証
  2. より明示的なセキュリティ対策
  3. rel="noreferrer"のリファラ制御機能

これらのツールが依然としてrel="noopener"の警告を出すのは、レガシーブラウザ対応を前提とした後方互換性の考慮によるものである。

まとめ

rel="noopener"はかつて重要なセキュリティ対策であったが、現在では主要ブラウザの標準動作に組み込まれ、明示的な指定は基本的に不要になった。ただし、後方互換性やリファラ制御の目的で、引き続きrel="noopener noreferrer"を指定することも有効である。

ウェブ開発においては、常に最新のセキュリティベストプラクティスを取り入れ、安全性と後方互換性のバランスを考慮することが重要である。

参考資料