リンクの「新しいタブで開く」に潜む罠。今すぐ `rel=”noopener”` を入れるべき技術的理由
フロントエンド開発の現場で、何気なく書いている `` 。これ、実は単なる「リンクを別タブで開く」というUI上の挙動だけを意味しているわけではありません。
もしあなたが今日まで、この属性に何のセキュリティ対策も施していなかったなら……この記事を読み終える頃には、恐らく背筋が凍るはずです。なぜなら、そのリンクをクリックした瞬間に、あなたのサイトのユーザーが「悪意ある攻撃者」に操作されるリスクを放置している可能性があるからです。
今日は、中級エンジニアなら絶対に押さえておくべき `rel=”noopener”` と `rel=”noreferrer”` の真実について、現場の視点から深掘りします。
—
なぜ `target=”_blank”` は危険なのか?
原因は、ブラウザの仕様にあります。`target=”_blank”` を指定して別タブでリンクを開くと、新しいページ(遷移先)からは `window.opener` というプロパティを通じて、元のページ(遷移元)の `window` オブジェクトにアクセスできてしまいます。
裏側で何が起きているのか
攻撃者が管理するサイトにユーザーを誘導した場合、そのサイトのJavaScriptは以下のように元のページを書き換えることが可能です。
// 攻撃者のサイトで実行される悪意あるコード
if (window.opener) {
// 元のページをフィッシングサイトへ強制的にリダイレクトさせる
window.opener.location.href = ‘https://malicious-site.com/fake-login’;
}
ユーザーは「元のページを開いたまま別タブを見ている」つもりでも、実は元のページは既に攻撃者の手によって偽のログイン画面にすり替えられている……。これが `window.opener` を悪用した「タブ・ナッピング(Tabnabbing)」という攻撃手法です。
—
解決策:rel属性による「縁切り」
この脆弱性を防ぐために導入されたのが `rel=”noopener”` です。これを指定すると、ブラウザは新しいページに対して `window.opener` を `null` として渡します。つまり、遷移先から遷移元への制御を完全に遮断するわけです。
使い分けのベストプラクティス
- `rel=”noopener”`: 必須。`window.opener` へのアクセスを無効化します。現在のモダンブラウザでは、`target=”_blank”` を指定すると自動的に `noopener` が付与される仕様(Chromium系など)も増えていますが、非対応ブラウザへの保険として手動付与が鉄則です。
- `rel=”noreferrer”`: `noopener` の機能に加え、遷移先へ `Referer` ヘッダー(どのページから来たかという情報)を送らないようにします。プライバシーをより厳格に守りたい場合や、解析ツールに情報を渡したくない場合に併用します。
—
実践的サンプルコード
現場のプロジェクトでそのまま使える、セキュアなリンクの記述例です。Reactなどのコンポーネントライブラリでも、基本的な考え方は変わりません。
—
シニアからのアドバイス:自動化のススメ
ここまで読んで「既存の何百個もあるリンクを全部修正するなんて……」と絶望した方もいるかもしれません。しかし、フロントエンドエンジニアには強力な武器があります。
もしプロジェクトがTypeScriptやReact環境なら、ESLintのルールで強制的にチェックを入れましょう。
// .eslintrc の設定例
{
“rules”: {
“react/jsx-no-target-blank”: [“error”, { “enforceDynamicLinks”: “always” }]
}
}
このように設定しておけば、開発中に `target=”_blank”` を書いた瞬間にエディタが警告を出してくれます。人間が一つひとつ記憶してチェックする時代は終わりです。仕組みでミスを防ぐことこそが、プロフェッショナルな開発のあり方です。
—
まとめ
1. `target=”_blank”` には必ず `rel=”noopener”` をセットにする。
2. `window.opener` を経由した攻撃は実在する脅威であると認識する。
3. 手動チェックではなく、Lintツールを活用して「仕組み」で防ぐ。
セキュリティ対策とは、時として地味で面倒な作業の積み重ねです。しかし、こうした細かい気配りが、あなたの担当するプロダクトの信頼性を支える強固な土台になります。
今日からあなたのコードに、これらの属性を書き加えてみてください。それだけで、あなたのサイトを訪れるユーザーは一歩分、確実に守られます。それでは、良いコードライフを!

コメント