[13] [[HTTP]] の [DFN[[CODE(HTTP)@en[[[X-Frame-Options:]]]]]] [[ヘッダー]]は、その[[HTTP応答]]に含まれる[[文書]]を[[フレーム]]により埋め込んで表示して良いかどうかを表します。
主として[[クリックジャッキング]]対策のために使われます。

[44] この[[ヘッダー]]は [[CSP]] [CODE(HTTP)@en[[[frame-ancestors]]]] [[指令]]により[[廃止]]されました [SRC[>>43]]。
しかし現在でも複雑な [[CSP]] よりも単純な [CODE(HTTP)@en[[[X-Frame-Options:]]]]
が好まれることがあります。

* 仕様書

[REFS[
- [12] '''[CITE@en[RFC 7034 - HTTP Header Field X-Frame-Options]] ([TIME[2014-03-02 14:15:03 +09:00]] 版) <http://tools.ietf.org/html/rfc7034>'''
- [38] [CITE@en[Content Security Policy 1.1]] ([TIME[2014-04-25 08:24:00 +09:00]] 版) 
<http://w3c.github.io/webappsec/specs/content-security-policy/csp-specification.dev.html#h5_frame-ancestors>
-- [43] [CITE@en[Content Security Policy]] ([TIME[2015-01-29 17:44:59 +09:00]] 版) <https://w3c.github.io/webappsec/specs/content-security-policy/#frame-ancestors-and-frame-options>
]REFS]

* 用法

[16] [[HTML]] では [CODE(HTMLe)@en[[[iframe]]]] [[要素]]などによってある[[文書]]の中に他の[[文書]]を埋め込むことができますが、
これを悪用し、[[利用者]]が気づかない内に埋め込まれた[[文書]]内を[[クリック]]させ、
[[利用者]]が意図しない動作を引き起こさせる「[[クリックジャッキング]]」攻撃があります。
これを防ぐため、自身を他のサイトに埋め込んで表示することを拒む [CODE(HTTP)@en[[[X-Frame-Options:]]]]
[[ヘッダー]]を指定することができます。

* 値

[19] 値としては、次の3種類のいずれか1つを指定できます [SRC[>>12]]。これらは[[大文字・小文字不区別]]です [SRC[>>12]]。

[FIG(railroad)[
= |
== [CODE(HTTP)@en[[[DENY]]]]
== [CODE(HTTP)@en[[[SAMEORIGIN]]]]
== [CODE(HTTP)@en[[[ALLOW-ORIGIN]]]] ...
]FIG]

[20] [DFN[[CODE(HTTP)@en[[[DENY]]]]]] の場合、[[フレーム]]内に表示しては[['''なりません''']] [SRC[>>12]]。

[21] [DFN[[CODE(HTTP)@en[[[SAMEORIGIN]]]]]] の場合、異なる[[起源]]のページの[[フレーム]]内に表示しては[['''なりません''']]
[SRC[>>12]]。[[起源]]が同じか判断できなければ、 [CODE(HTTP)@en[[[DENY]]]] のように扱わなければ[['''なりません''']] [SRC[>>12]]。

;; [22] [[起源]]が同じか判定できないとはどのような場合なのでしょうか・・・。

[23] 同じ[[起源]]かどうかの判定の対象が[[フレーム]]を含むページである[[Webブラウザー]]と、
[[最上位閲覧文脈]]である[[Webブラウザー]]や、先祖[[閲覧文脈]]すべての[[Webブラウザー]]があります [SRC[>>12]]。

;; [24] 現状違っているのは仕方ないとして、どちらであるべきなのかは定義されていません。
それを決めるのが仕様書の役割だと思うのですが・・・。

[25] [DFN[[CODE(HTTP)@en[[[ALLOW-ORIGIN]]]]]] の後に[[スペース]]が続き、その後に [[serialized-origin]]
([[妥当な起源]])
が続く場合、[[最上位閲覧文脈]]が指定された[[起源]]でなければ、表示しては[['''なりません''']] [SRC[>>12]]。

[FIG(railroad)[
= [CODE(HTTP)[[[ALLOW-ORIGIN]]]]
= [CODE(charname)@en[[[SP]]]]
= [[起源]]の[[ASCII直列化]]
]FIG]

[26] 「ドメインアドレスより後のデータ ([CODE[[[/]]]] より後のデータ) は無視される [SRC[>>12]]」とあります。
[[起源]]だけでなく [[URL]] [[path]] が指定されていた場合ということなのでしょうか。意図が不明瞭です。

;; [33] [CODE(HTTP)@en[[[ALLOW-ORIGIN]]]] は [[IE]] 拡張で、他の [[Webブラウザー]]は実装していないことがあります [SRC[>>12]]。

;; [39] [[CSP]] の [CODE(HTTP)@en[[[frame-ancestors]]]] は、先祖すべての[[閲覧文脈]]と比較することになっています [SRC[>>38]]。

[27] [[起源]]の比較は [[RFC 6454]] に従い行う[['''べきです''']] [SRC[>>12]]。
しかし既存の実装は[[ポート]]の違いを無視しています [SRC[>>12]]。

;; [28] なぜ[['''必須''']]ではなく[['''推奨''']]なのでしょうか。また、[[ポート]]を無視するという情報は有用ですが、
であるから互換性のためにそれに倣うべきなのか (それなら[['''推奨''']]と矛盾してしまいますが...)、
それとも[[ポート]]を無視しないようにしていくべきなのか。標準化を通して[[相互運用性]]を向上させようという意欲が感じられません・・・。

[29] ここでいう[[スペース]]は、1文字以上の [[SP]] や [[HTAB]] ですが、1文字の [[SP]]
とする[['''べきです''']] [SRC[>>12]]。また解釈前や[[下流]]への転送前に1文字の [[SP]]
にまとめるか、 [[SP]] に置き換える[['''べきです''']] [SRC[>>12]]。

* 適用対象

[30] [[フレーム]]の表示には例えば次のものが含まれます:
[CODE(HTMLe)@en[[[iframe]]]], [CODE(HTMLe)@en[[[frame]]]], [CODE(HTMLe)@en[[[object]]]],
[CODE(HTMLe)@en[[[embed]]]], [CODE(HTMLe)@en[[[applet]]]] [SRC[>>12]]。
[[プラグイン]]内の表示も含まれます [SRC[>>12]]。

[31] [[HTML]] の表示が対象 [SRC[>>12]] と書かれていますが、 [[XML]] など他のものも対象となっているはずです
(そうでないと意味がありません)。

[42] 表示は行われませんが、 [[HTTP]] 層の処理は行われます。例えば [CODE(HTTP)@en[[[Set-Cookie:]]]]
ヘッダーがあれば、その処理は通常通り行われます。

* 処理モデル

[32] [[フレーム]]の表示が禁止されていれば、ただちに[[ダウンロード]]や[[構文解析]]を[RUBYB[中止]@en[abort]]して[['''構いません''']]。
[[ブラウザー]]はできるだけすぐに「フレームなし」ページにリダイレクトする[['''べきです''']]。
そのページには [[URL]] を表示したり、新しい窓で開くオプションを提示したりできます。
実装によっては空のフレームを表示するだけだったりします。 [SRC[>>12]]

[40] [[CSP]] の [CODE(HTTP)@en[[[frame-ancestors]]]] が指定されていれば、そちらが優先される[['''べきです''']]。
[CODE(HTTP)@en[[[X-Frame-Options]]]] は無視される[['''べきです''']]。 [SRC[>>38]]

;; [41] なぜ[['''必須''']]ではなく[['''推奨''']]なのか謎です。動作が実装ごとに異なっていてはセキュリティーホールになりかねないと思いますが。

* キャッシュ

[34] [CODE(HTTP)@en[[[X-Frame-Options]]]] の[[キャッシュ]]は推奨されません。現状どの[[Webブラウザー]]もキャッシュしていません。
[SRC[>>12]]

[35] [[サーバー]]は[[要求]]元 (の [CODE(HTTP)@en[[[Origin:]]]] など) を見て [CODE(HTTP)@en[[[X-Frame-Options:]]]]
を変えることがあるので、キャッシュするべきではありません [SRC[>>12]]。

;; [36] しかし [CODE(HTTP)@en[[[X-Frame-Options:]]]] だけキャッシュしないわけにもいかないので、
安全側に倒すと、[[応答]]全体がキャッシュできないのですかね?

* 実装

[REFS[
- [1] [CITE@en-us[The X-Frame-Options response header - MDC]]
([TIME[2010-10-27 15:11:17 +09:00]] 版)
<https://developer.mozilla.org/en/the_x-frame-options_response_header>
]REFS]

* 歴史

** IE8

[14] 2009年に [[IE8]] が初めて実装しました。

[REFS[
- [2] [CITE@en[IEBlog : IE8 Security Part VII: ClickJacking Defenses]] ([TIME[2009-01-31 00:57:05 +09:00]] 版) <http://blogs.msdn.com/ie/archive/2009/01/27/ie8-security-part-vii-clickjacking-defenses.aspx>
- [3] [CITE@en[Combating ClickJacking With X-Frame-Options - IEInternals - Site Home - MSDN Blogs]] ([TIME[2012-11-18 02:39:57 +09:00]] 版) <http://blogs.msdn.com/b/ieinternals/archive/2010/03/30/combating-clickjacking-with-x-frame-options.aspx>
]REFS]

** 追随

[15] [[IE]] 以外の [[Webブラウザー]]もすぐに追随して実装しました。

[REFS[
- [6] [CITE[690168 – Implement Allow-From syntax for X-Frame-Options]] ([TIME[2012-11-18 02:44:50 +09:00]] 版) <https://bugzilla.mozilla.org/show_bug.cgi?id=690168>
- [5] [CITE[Bug 94836 – Support for X-Frame-Options: Allow-From '''['''uri''']''']] ([TIME[2012-11-18 02:43:58 +09:00]] 版) <https://bugs.webkit.org/show_bug.cgi?id=94836>
]REFS]

** 標準化

[REFS[
- [8] [CITE@en[draft-ietf-websec-frame-options-00 - HTTP Header Frame Options]]
( ([TIME[2012-10-14 12:33:27 +09:00]] 版))
<http://tools.ietf.org/html/draft-ietf-websec-frame-options-00>
- [4] [CITE@en[draft-ietf-websec-x-frame-options-01 - HTTP Header X-Frame-Options]] ([TIME[2012-10-23 08:15:27 +09:00]] 版) <http://tools.ietf.org/html/draft-ietf-websec-x-frame-options-01>
]REFS]

[7] 初期案では [DFN[[CODE(HTTP)@en[[[Frame-Options:]]]]]], [DFN[[CODE(HTTP)@en[[[Frame-Option:]]]]]]
といった名前でしたが、その後実際に使われている [CODE(HTTP)@en[[[X-Frame-Options:]]]] に変更されています。

[9] ( ([TIME[2010-07-20 19:05:29 +09:00]] 版))
<http://seclab.stanford.edu/websec/framebusting/framebust.pdf>

[10] [CITE@en[Coordinating Frame-Options and CSP UI Safety directives]]
( ([[Hill, Brad]] 著, [TIME[2012-07-10 03:31:42 +09:00]] 版))
<http://lists.w3.org/Archives/Public/public-webappsec/2012Jul/0014.html>

[17] [[RFC 7034]] は、 [[RFC 6648]] で [CODE(HTTP)[[[X-*]]]] が[[非推奨]]とされていることを理由に [[CSP]]
に置き換えられる [SRC[>>12]] と述べています。

;; [18] [[RFC 7034]] は既に [CODE(HTTP)[[[X-*]]]] の名前が使われているものを破棄させることを意図してはいないと思うのですが・・・。

[37] [[RFC 7034]] は2013年に発行された比較的新しい仕様書でありながら、
[[CSP]] に移行するべきという理由で細部を明確に規定しておらず、
[[fetch]] や [[navigate]] のような近代的な用語を用いておらず、
[[browsing context]] もほとんど言及がない前近代的な文書となっています。

[11] [CITE[IRC logs: freenode / #whatwg / 20130717]]
( ([TIME[2013-07-20 20:18:32 +09:00]] 版))
<http://krijnhoetmer.nl/irc-logs/whatwg/20130717#l-203>

[45] [CITE[IRC logs: freenode / #whatwg / 20151002]]
([TIME[2015-10-03 16:16:15 +09:00]] 版)
<http://krijnhoetmer.nl/irc-logs/whatwg/20151002>

[46] [CITE@en[User Interface Security and the Visibility API]]
([TIME[2015-12-08 03:20:38 +09:00]] 版)
<https://w3c.github.io/webappsec-uisecurity/>

[48] [[CSP2]] には [[CSP]] [CODE[frame-ancestors]] と [CODE(HTTP)@en[X-Frame-Options:]]
との関係が一応規定されていました [SRC[>>47]] が、
[[CSP]] と [[Fetch]] の関係を明確化した [[CSP3]] では当該部分が削除されています
[SRC[>>49]]。 従って現状 [CODE(HTTP)@en[X-Frame-Options:]]
を処理するべき正確なタイミングはどこでも規定されていません。
[TIME[2016-03-15T08:47:33.900Z]]

[REFS[
- [47] [CITE@en[Content Security Policy Level 2]] ([TIME[2016-02-29 23:20:13 +09:00]] 版) <https://w3c.github.io/webappsec-csp/2/#frame-ancestors-and-frame-options>
- [49] [CITE@en[Content Security Policy: Document Features]] ([TIME[2016-02-29 23:20:13 +09:00]] 版) <https://w3c.github.io/webappsec-csp/document/>
]REFS]

[50] [CITE@en[Issue 610284 - chromium - Regression: 'Download as PDF' option is not working on 'www.chromium.org/Home'. - Monorail]]
( ([TIME[2016-05-15 11:32:08 +09:00]]))
<https://bugs.chromium.org/p/chromium/issues/detail?id=610284>

[51] [[クリックジャッキング]]防止のために無条件で本[[ヘッダー]]を指定するような[[サーバー]]もあるようですが、
本当に指定する必要があるのかどうかはケースバイケースです。よく検討する必要がありそうです。

[52] [CITE@en['frame-ancestors' obsoletes 'X-Frame-Options']]
([[mikewest]]著, [TIME[2017-03-03 02:25:15 +09:00]])
<https://github.com/w3c/webappsec-csp/commit/2831e21665d4c2d0dc577b63736d271f1339f08c>

[53] [CITE@en[Fix X-Frame-Options issue link]]
([[annevk]]著, [TIME[2017-11-28 00:47:56 +09:00]])
<https://github.com/whatwg/html/commit/ede1de13e9aa97b3bfeb958ad59705160e4976c9>

[54] [CITE@en[Fix X-Frame-Options issue link by annevk · Pull Request #3258 · whatwg/html]]
([TIME[2017-11-30 23:39:35 +09:00]])
<https://github.com/whatwg/html/pull/3258>

[55] [CITE@en[Consider making `X-Frame-Options: deny` to create a new browsing context group · Issue #4218 · whatwg/html · GitHub]]
([TIME[2019-01-08 10:40:12 +09:00]])
<https://github.com/whatwg/html/issues/4218>

[56] [CITE@en[Consider making `X-Frame-Options: deny` to create a new browsing context group · Issue #4218 · whatwg/html]]
([TIME[2019-02-16 18:55:19 +09:00]])
<https://github.com/whatwg/html/issues/4218>

[57] [CITE@en-US[X-Frame-Options - HTTP | MDN]]
([TIME[2021-08-19T01:40:45.000Z]], [TIME[2021-08-19T03:18:19.092Z]])
<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options>