ウェブサイトを運営する際、外部リンクを新しいタブやウィンドウで開くために、リンクにtarget="_blank"
を指定することがあります。しかし、この指定だけではセキュリティ上のリスクが生じる可能性があります。そこで、rel
属性にnoopener
やnoreferrer
を追加することが推奨されています。この記事では、noopener
とnoreferrer
の違い、サポートブラウザの違い、両方を併用する理由、そしてそれぞれの使い分けについて解説します。
noopenerとは?
<a href="..." target="_blank" rel="noopener">リンク</a>
noopener
は、リンク先のページが元のページ(リンク元)への参照を持たないようにするための値です。具体的には、target="_blank"
を指定したリンクをクリックすると、新しいタブやウィンドウでリンク先が開かれますが、その際、リンク先のページからwindow.opener
プロパティを介してリンク元のページにアクセスできてしまいます。これにより、リンク先のページがリンク元のページを操作するリスクが生じます。rel="noopener"
を指定することで、window.opener
プロパティがnull
となり、リンク先からリンク元へのアクセスを防ぐことができます。
noreferrerとは?
<a href="..." target="_blank" rel="noreferrer">リンク</a>
noreferrer
は、noopener
の機能に加えて、リンク元のURL情報(リファラー)をリンク先に送信しないようにするための値です。通常、リンクをクリックすると、リンク元のURLがリファラーとしてリンク先に送信されますが、rel="noreferrer"
を指定することで、これを防ぐことができます。これにより、プライバシーの保護や、リンク元の情報漏洩を防ぐことが可能となります。
サポートブラウザの違い
noopener
とnoreferrer
のサポート状況はブラウザによって異なります。主要なブラウザの対応状況は以下の通りです。
noopenerをサポートするブラウザ
noopener
は比較的新しい仕様で、対応しているブラウザは後述のnoreferrer
と比べると狭くなります。

noreferrerをサポートするブラウザ
前述のnoopener
と比べると対応しているブラウザの範囲は広くなります。

両方を同時に指定することが推奨されていたのは何故か?
<a href="..." target="_blank" rel="noopener noreferrer">リンク</a>
ここまで見ると、noreferrer
はカバーしている機能もサポートブラウザもnoopener
よりも広いため同時に指定する理由はないように見えます。
では何故同時に推奨されていた時期があったのでしょうか?
この点について理解するためにnoopener
とnoreferrer
に関する議論をいくつか調べました。
同時に指定することを推奨されていた理由
過去の話であるため、どこまで信憑性があるかは不明ですが、次のような理由でnoopener
とnoreferrer
を両方指定することが推奨されていた時期があったようです。
- 仕様に準拠していないレガシーブラウザに対応するため
- Firefox 33-35で発生していた不具合に対する対策
非準拠ブラウザに対する対策
仕様に準拠していないブラウザでnoreferrer
を指定してもwindow.opener
がnull
にならないことに対する対策として、noopener
を同時に指定していた、そういうブラウザが存在する可能性を想定して同時に指定していたようです。
@seancrater I don’t; the spec is often aspirational, and doesn’t describe historical (noncompliant) engines.
In general, if any version of any browser ever required both, then we should use both for the foreseeable future.
確かに、過去ChromeとFirefoxで動作が異なったり、一部のブラウザで問題が起きるといったことはありました。以下の記事では、EdgeでYahoo! Japanを表示したときに正しく表示されないという問題について問い合わせています。
今後もこのように特定のブラウザの特定のバージョンでのみ不具合が起きる可能性を考慮し、同時に指定することに対して、若干バンドルサイズが大きくなることしかデメリットがないことを考えると両方を指定しておくことは心理的安心という面からも適切な判断だと考えられます。
Firefox 33-35で発生してた不具合に対する対策
もう一つの理由はFirefox 33-35で発生していた、noreferrer
を指定すると別タブで開けなくなる不具合に対する対策で、ESLintのIssueでこの点について議論されています。
Actually, I found a counter-example: Firefox 33–35 removes opener with
rel="noreferrer"
but doesn’t withrel="noreferrer noopener"
(probably because it encounters an unsupportedrel
value). If you have a Browserstack account, you can verify it by opening http://noreferrer.hypnosphi.de (source) in FF 33–35 and clicking the links there.
Firefox側のIssueを見ると、noreferrer
をつけていてもリファラーを送っているとありますが、これがwindow.opener
がnull
になっていないことと同じことなのかは今ひとつわかりませんでした。
If you open a link with the rel=”noreferrer” attribute in a new tab (eg. over middle click) it will send a referrer anyway.
ESLintではnoopener
とnoreferrer
を両方指定するようにチェックしていた時期がありましたが、現在ではnoreferrer
がついていることをチェックし、noopener
もついているかどうかはチェックしないようになっています。
WordPressでrel=”noopener”が自動付与される理由
WordPressでは、バージョンによって、target="_blank"
を持つリンクにrel="noopener"
が自動付与されるのか、rel="noopener noreferrer"
が付与されるのかが変わっていたようです。
WorkPress 4.7.4からセキュリティ対策のためにrel="noopener noreferrer"
が自動的に付与されるようになりました。しかし、WordPress 4.8では、rel="noopener"
だけが自動付与されるように変更されています。
WordPress 5.0では新しいエディタ「Gutenberg」が導入され、rel="noopener noreferrer"
が自動付与されるようになった一方で、クラシックエディタを使用している場合にはrel="noopener"
だけが自動付与されるようになっていました。
WordPress 5.6ではrel="noopener"
だけが自動付与されるようになり、以降はrel="noopener"
だけが自動付与される仕様に落ち着いているようです。
WordPressが、rel="noreferrer"
ではなくrel="noopener"
を付与しているのは、セキュリティ対策をしつつアフィリエイトリンクなどのためにリファラーを送りたい(参照元を知らせたい)という点にあります。認証が必要なページと違って、ページのURLを知ってもらう機会を少しでも減らさないためにも、noreferrer
ではなくnoopener
が求められます。
パフォーマンス対策としてのnoopener
仕様には記載がなく、実装依存の話としてnoopener
を指定する効果のひとつにパフォーマンス対策を挙げている記事を見かけます。しかし、この主張は必ずしも正しいというわけではなく、ブラウザの実装依存であるという点は理解しておく必要があります。
window.opener
がnull
でない場合、元ページを開いているタブとtarget="_blank"
で開いたページのタブは同じプロセス・スレッドで動作することになり、開いたページで重いスクリプトを実行すると、元ページのパフォーマンスにも影響を与えるというものです。
実際のブラウザのコードを見たわけではありませんが、最近のバージョンではここら辺は対策済みになっているのではないかと思います。タブの数だけスレッドが作成されるわけでもありませんし、特のタブが応答しなくても他のタブは問題なく操作できているので、主要ブラウザではこの点はあまり気にする必要がないと思います。
結局、どれを付与すればよいのか?
noopener
とnoreferrer
のどちらを付与すればよいかについてまとめます。
「どちらも付与しない」は非推奨
タブブラウザが登場する以前ならまだしも、現在のブラウザではtarget="_blank"
を指定した場合はnoopener
かnoreferrer
のいずれかを指定すべきです。特に外部サイトのページをtarget="_blank"
で開く場合はrel
属性を付与することは必須であるといっても差し支えないと思います。
同一サイト内であっても、モードレスダイアログのようなユーザー体験を実現したければ、別タブで操作させるのではなく、同一タブ内にモードレスダイアログをHTML/CSS/JSを使って実現すれば済むので、そういった意味でもwindow.opener
を使うことはもうないのではないかと思います。
認証が必要なページから外部ページを開くときはnoreferrer
を指定する
認証されたユーザーのみが表示できるページで外部ページを開くときはそのページのURLを知られないようにするという意味でもnoreferrer
を指定することが強く推奨されます。
もう少し簡単に言ってしまえば、リファラーを送りたいケース以外はnoreferrer
を指定するのがよいと思います。noreferrer
の方がサポートされているブラウザの範囲が広いため、セキュリティ対策を考えるとnoreferrer
を使う方が安全なためです。
リファラーを送信する必要がある場合のみnoopenerを指定する
ブログやアフィリエイトサイトなど、target="_blank"
で表示したサイトに元ページのURLを伝えたい、流入元がどこかを伝えたいというケースにおいてはnoopener
を指定するのがよいでしょう。
WordPressがnoreferrer
を自動付与せずnoopener
を自動付与しているのはこれが理由だと考えられます。アフィリエイトの種類にもよりますが、リファラーがないとアフィリエイト報酬に計算されない場合もnoreferrer
ではなくnoopener
を使う必要があるので、アフィリエイトサイトの仕様を事前に確認しておくことが重要です。
rel属性が設定されていることをチェックしよう
基本的にはESLintなどの静的解析ツールでチェックするのが望ましいですが、アプリケーション開発ではURL部分が変数になることがあり、この場合は静的解析ツールではチェックしきれないという問題があります。
そのため、静的解析だけを頼りにするのではなく、他の手段も組み合わせて多層的にチェックするのがよいでしょう。
静的解析ツールでチェックする
チェック漏れを防ぐという点ではESLintなどの静的解析ツールを導入し、エディタの拡張機能でチェックしたり、CIでチェックすることは非常に重要です。しかし、すべてのケースをチェックしきれなかったり、必要ない場合でもエラーになるなどの弊害もあるため、導入できるかどうかはチームで慎重に検討することが望ましいです。
ESLintでチェックする場合、
npm install --save-dev eslint @html-eslint/parser @html-eslint/eslint-plugin
でHTMLファイルをチェックするためのプラグインも導入します。
設定ファイルでは、
import html from "@html-eslint/eslint-plugin";
import htmlParser from "@html-eslint/parser";
...
export default defineConfig([
...
{
files: ["**/*.html"],
plugins: {
"@html-eslint": html,
},
languageOptions: { parser: htmlParser },
rules: {
"@html-eslint/no-target-blank": "error",
},
},
]);
HTMLファイルを処理するルールを追加することで、HTMLファイルに対してLintingできるようになります。
a
タグにtarget="_blank"
があり、href
属性が相対パスでない場合に、rel="noreferrer"
がないと
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<a target="_blank" href="http://example.com/">Home</a>
</body>
</html>
以下のようにエラーが出るようになります。
> test1@1.0.0 lint
> eslint *.html
/Users/user/test/index.html
9:8 error Missing `rel="noreferrer"` attribute in a tag @html-eslint/no-target-blank
相対パスの場合はチェックが行われない点に注意が必要です。(あくまでも外部サイトを表示するためのセキュリティ対策にフォーカスされている)
また、先ほど参照したESLintのIssueでも触れられていますが、noopener
の有無はチェックしないようになっているので、rel="noreferrer"
かrel="noopener noreferrer"
(順不同)のいずれかの場合にパスするようになっているため、noopener
があることをチェックできない点にも注意してください。
CopilotなどのAIエージェントにチェックしてもらう
Copilotなどソースコードを参照できるAIエージェントにチェックしてもらうというのも手です。ワークスペース全体をチェックできる場合は網羅的にチェックしてもらえるので、非常に効率的です。
レビューの観点に加える
修正箇所に限定するのであれば、プルリクなどのレビューの観点としてリンク使用時にrel
属性を付与しているかをチェックするのもよいでしょう。ただし、チェック漏れのリスクもあるため、前述のようなツールでのチェックを併用したり、チェックリストでのチェックを行うなどの対策を併用することも検討すべきです。
まとめ
noopener
とnoreferrer
を指定することでどういった効果があるのか、これらのrel
属性に対して過去にどのような経緯があったのかについて確認しました。
また、現在においてはどのように指定すればいいのか、どうやってrel
属性の付与漏れを防ぐのがよいかについてもまとめました。
動作確認という点では、rel
属性の有無にかかわらず問題なく動いてしまうので、発見しにくい問題ではありますが、セキュリティに関する重要な対策の1つであるため、ツールなども活用しながら付与漏れがないようにしていくことが重要です。
昨今ではCopilotなどでワークスペース全体をチェックすることも可能になってきているので、今一度点検をしてみてもよいかもしれません。