1. イントロダクション
このセクションは規範的ではありません。
ウェブアプリケーションは、ユーザーのコンピュータにデータをローカル保存して、ユーザーがオフライン中も機能を提供し、オンライン中のパフォーマンスも向上させます。これらのローカルキャッシュは、ユーザーと開発者の双方に大きな利点をもたらしますが、リスクも存在します。
ユーザーのデータは機微かつ価値あるものです。ウェブ開発者はそれを保護するために合理的な手段を講じるべきです。その一つは保存前にデータを暗号化すること、また別の一つは不要になったデータをユーザーのマシンから削除することです(たとえばアプリからサインアウトしたときやアカウントを削除したとき)。
サイトの作者はJavaScriptで多数のストレージ機構からデータを削除できますが、確実な対応が困難なものもあります。例えばクッキーは、JavaScriptのdocument.cookieアクセスで一部をクリアできますが、HttpOnlyクッキーはHTTPレスポンス内の複数のSet-Cookieヘッダを使った場合のみクリア可能です。全ホストのクッキーを知っている必要があり、これは複雑です。キャッシュはさらに困難で、ブラウザのネットワークキャッシュに命令的にアクセスする手段はそもそもありません。
本書は、これらや他のローカルストレージからデータを削除するための新たな仕組みを定義し、ウェブ開発者がClear-Site-Data HTTPレスポンスヘッダを通じて、ユーザーのローカルデータキャッシュをクリアできるようにします。
1.1. 例
1.1.1. サインアウト
https://supersecretsocialnetwork.example.com/logoutからSuper Secret Social
Networkをサインアウトし、
サイト作者はローカル保存データが削除されることを望んでいます。
そのために、レスポンスに次のHTTPヘッダを送信できます:
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
1.1.2. ターゲットを絞ったクリア
https://megacorp.example.com/logoutからサインアウトします。Megacorpは多数のサービスがサブドメインで存在し、どれをログアウト時にクリアして安全か一概に判別できません。一案は全てクリアし、問題はその後で処理することですが、CEOは「Irate
Ibexes」での長時間の進捗が誤消去で失われた経験から全消去を拒否しています。
しかし開発者は「Minus」アプリケーションだけは安全であると把握しているため、ログアウト時ランディングページでこのサブドメインに対しCORS対応・CSRF対策POSTをリクエストとして組み込むことで個別にクリアできます:
fetch("https://minus.megacorp.example.com/clear-site-data",
{
method: "POST",
mode: "cors",
headers: new Headers({
"CSRF": "[insert sekrit token here]"
})
});
そのエンドポイントはプリフライトには正しいCORSヘッダを返し、本リクエストには次のヘッダを返してください:
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
1.1.3. 重要なCookieを保持
https://ads-are-awesome.example.com/optout
にCSRF対策POSTで興味関心広告からオプトアウトします。サイト作者はトラッキング情報を含む可能性のある DOM
アクセス可能データを削除しますが、行ったばかりのオプトアウトクッキーが一緒に消えるのは避けたい。
そのためには "cookies" を除き、他すべての型を含めて次のHTTPヘッダを送信します:
Clear-Site-Data: "cache", "storage", "executionContexts"
1.1.4. キルスイッチ
このような永続化クライアントサイドXSSのリスクを下げるため、ローカルのデータソースを消し去る次のHTTPヘッダをレスポンスで送信できます:
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
注: Service Worker を導入すると、リクエストは約24時間ごとに必ずサーバへ送られます。更新時のping時に、このようなヘッダを障害時用に送信するとよいでしょう。 [SERVICE-WORKERS]
1.2. 目的
一般的には、ウェブ開発者が各オリジンのユーザーエージェントによるローカルデータ保存について、よりコントロールしやすくすることを目的としています。特に開発者は、下記のことを信頼性高く実現できるべきです:
-
[INDEXEDDB]・WebSQL・Filesystem・
localStorage・sessionStorageのようなオリジンのクライアントサイドストレージ機構内のデータがクリアされること。 -
オリジンのホストに設定されたクッキーが削除されること [RFC6265]。
-
オリジンのWeb Worker(専用・共有)が終了されること。
-
オリジンに登録されたService Workerが終了・登録解除されること。
-
オリジン由来のリソースがユーザーエージェントのローカルキャッシュから消去されること。
-
上記全てがHTTPSオリジンのHTTP版にも伝播されること。
-
上記のいずれも、悪意のあるアクティブなドキュメントがメモリに面白いデータを保持し、それがクリアされたら再設定することでバイパスされないこと。
2. インフラストラクチャ
本書はABNF文法を[RFC5234]で定義し[RFC7405]で更新され、RFC7230・セクション7で定義された#rule拡張と、同文書のセクション3.2.6で定義されているquoted-stringルールを用いて構文を記述しています。
また本書アルゴリズムや本文上の基本的概念の多くはInfra Standard [INFRA] を参照します。
3. サイトデータのクリア
開発者はリクエストに対するレスポンスで Clear-Site-Data HTTPレスポンスヘッダを配信することで、ユーザーエージェントにさまざまな関連データのクリアを指示できます。
3.1. Clear-Site-Data HTTPレスポンスヘッダーフィールド
Clear-Site-Data
HTTPレスポンスヘッダーフィールドは、ユーザーエージェントに対し、特定種類のすべてのデータを削除すべきであることを通知します。このヘッダーは次の文法で表現されます:
Clear-Site-Data = 1#( quoted-string ) ; #rule はRFC7230のセクション7で定義されています。
§3.2 Fetch統合 および §4.1 パース でClear-Site-Data ヘッダーの処理方法を記述します。
この文書では、この仕組みでクリアできる既知のデータ型の初期セットを定義します。下記に説明があります。将来のバージョンでは、このヘッダーで追加のデータ型をサポートでき、その場合はquoted-string文法に準拠する必要があります。ユーザーエージェントは、ヘッダーのパース時に未知の型を無視しなければなりません(MUST)。
- "
cache" -
"
cache"型は、サーバーが特定オリジンの response の url に関連付けられたローカルキャッシュデータを削除したいことを表します。これには当然ながらネットワークキャッシュも含まれますが、ユーザーエージェントが実装する他の多様なキャッシュ(プリレンダページ、スクリプトキャッシュ、シェーダキャッシュ等)のデータも削除します。実装詳細は§4.2.3 オリジンのキャッシュクリア参照。
https://example.com/clearからレスポンスが届いたとき、以下のヘッダーでオリジンhttps://example.comに関連するキャッシュがクリアされます:Clear-Site-Data: "cache"
注: キャッシュは通常オリジン単位ではなくURLやタイムスタンプ単位で管理されています。そのため、実際にはオリジン指定のキャッシュクリアは線形走査が必要となり、大きなキャッシュでは非常に高コストです。
- "
cookies" -
"
cookies"型は、サーバーが特定オリジンの response の url に関連付けられたクッキーを削除したいことを表します。クッキーに加え、HTTP認証認証情報 [RFC7235]、Channel ID [CHANNELID] や Token Binding [TOKBIND]等のオリジン依存トークンもクリアされます。実装詳細は§4.2.4 オリジンのクッキークリア参照。
https://example.com/clearからのレスポンス時、下記ヘッダーでオリジンhttps://example.comに関連するクッキー、並びに同じ登録ドメイン配下すべてのオリジンのクッキー(例https://www.example.com/やhttps://more.subdomains.example.com/)がクリアされます。Clear-Site-Data: "cookies"
- "
storage" -
"
storage"型は、サーバーが特定オリジンの response の urlに関連付けられたローカル保存データを削除したいことを表します。ここには(localStorage,sessionStorage, [INDEXEDDB], [WEBDATABASE]等)や、Service Worker登録のような周辺的仕組みも含みます。実装詳細は§4.2.5 オリジンのDOMアクセシブルストレージクリア参照。
https://example.com/clearからのレスポンス時、下記ヘッダーでhttps://example.comのDOMアクセシブルストレージがクリアされます:Clear-Site-Data: "storage"
- "
executionContexts" -
"
executionContexts"型は、サーバーが現在特定オリジンに対応してレンダリングしている response の url の実行コンテキストを無効化し再読み込みすることを表します。https://example.com/clearからのレスポンス時、下記ヘッダーでhttps://example.comの実行コンテキストが無効化・再読み込みされます:Clear-Site-Data: "executionContexts"
- "
*" -
"
*"(ワイルドカード)疑似型は、サーバーがすべての型を指定した場合と同じ効果をもたらすことを表します。https://example.com/clearからのレスポンス時、下記ヘッダーでhttps://example.comに関連するすべてのクッキー・キャッシュ・DOMアクセシブルストレージがクリアされ、同オリジンの実行コンテキストも無効化・再読み込みされます:Clear-Site-Data: "*"
注: ワイルドカードは将来型追加時にも前方互換的に全型をカバーします。
幅広いクリーニングが目的ならワイルドカードを使ってください(DO)。
上記4種の略記としてワイルドカードを使うのは推奨しません(DO NOT)。将来意味が変わるからです。
注: ここで定義した構文は本ドキュメント将来の拡張で、型指定により細かいフィルタが追加される場合も互換です。例として、"cookies"
の個別値除外機能拡張が予想されます。すべての型名を二重引用符で囲んでおくことで、簡単なカンマ分割処理からヘッダー値をJSONで解釈する高度処理に移行しても下位互換が保てます。
3.2. Fetch統合
Clear-Site-Data ヘッダーがネットワークから受信したHTTP
response
に存在する場合は、そのレスポンスをユーザーに表示する前にデータをクリアしなければなりません(MUST)。つまり、現行のHTTP-network fetchアルゴリズムのステップ14の後に、次のステップを実行します:
-
credentials flagがセットされ、かつresponseのheader listに
Clear-Site-Dataヘッダーが含まれていれば、§4.2 responseのデータクリア をresponseに対して実行する。
注:
これはSet-Cookieヘッダー処理の後に実行されます。クッキーをクリアする場合はすべて消去です。これは部分的なクッキー消去によるアプリケーションの不定/脆弱状態を避ける意図です。特定クッキーの削除はSet-Cookieヘッダで失効させることで行うべきです。
注: fetchのcredentials flagは本来クッキーの変更制限ですが、Clear-Site-Dataは一貫性の観点から全タイプにこの制約を適用します。
4. アルゴリズム
4.1. パース
responseが与えられたとき、ユーザーエージェントは responseの
Clear-Site-Data ヘッダーをパース して、タイプのリストを返すことができます。手順は次の通りです:
-
typesを空リストにする。
-
headerを、extracting header list values(引数
Clear-Site-Dataと responseのheader list)の結果とする。 -
headerが
nullまたはfailureなら空リストを返す。 -
header の各typeについて、最初に一致するものがあればその文を実行する(switch on type):
- `
"cache"` -
cache を types に追加
- `
"cookies"` -
cookies を types に追加
- `
"storage"` -
storage を types に追加
- `
"executionContexts"` -
executionContexts を types に追加
- `
"*"` -
cache、cookies、 storage、 executionContexts を types にすべて追加
- `
-
types を返す。
注: 現行の値は上のシンプルなswitch文で処理できます。今後型定義が複雑化した場合はパーサ全体をJSON処理に移行することになるでしょう。
4.2. response のデータクリア
response(response)が与えられたとき、ユーザーエージェントは responseのサイトデータクリア を次の手順で行えます:
-
もしresponseのurlがa priori authenticated URLでなければ、break。
-
typesを responseのClear-Site-Dataヘッダーをパースの結果とする。
-
browsing contextsを originとtypesのデータ消去準備の結果とする。
-
types の各typeについて:
-
最初に一致するものに応じて実行:
-
-
もしtypesが"executionContexts"を含むなら、browsing contextsをリロード。
注: ユーザーエージェントは開発者向けにクリア動作のデバッグ手段を提供することが推奨されます。例えば成功を示すコンソールメッセージやタイムラインエントリが該当します。
4.2.1. originのデータ消去準備
origin (origin) と type のリスト(types)が与えられたとき、ユーザーエージェントは originのデータ消去準備 を次の手順で行えます。このアルゴリズムは、消去されたデータをメモリ上のJavaScript変数から再生成できないように、サンドボックス化されたbrowsing contextのリストを返します。
-
sandboxedを空リストにする。
-
typesが"
executionContexts"を含まない場合、sandboxedを返す。 -
ユーザーエージェントの全browsing contextの各contextについて:
-
documentをcontextのactive documentとする。
-
もしdocumentのrelevant settings objectのoriginがoriginでなければ、continue
-
サンドボックスディレクティブのパースを空文字列を入力値、documentのactive sandboxing flag setを出力値として実行。
-
-
sandboxedを返す。
4.2.2. browsing contexts をリロードする
browsing contexts(contexts)のリストが与えられた場合、ユーザーエージェントは以下のように browsing contexts をリロードする ことができる:
-
contexts の各 context について:
-
context の active document の relevant settings object の global object の
Locationオブジェクトのreload()を実行する。これは最も単純な方法だが、おそらくドキュメントとそのコンテキストに少し深く入り込みすぎている。おそらく HTML から該当する部分を分解してコピー/貼り付けする必要がある。
-
4.2.3. origin のキャッシュをクリアする
origin(origin)が与えられた場合、ユーザーエージェントは以下のように origin のキャッシュをクリアする ことができる:
-
host を origin の host とする。
-
cache list を、network cache から、その
target URIの host が host と同一であるエントリの集合とする。 -
cache list の各 entry について:
-
entry を network cache から削除する。
-
-
ユーザーエージェントが純粋な network cache 以外のキャッシュを実装している場合、それらのキャッシュからも origin に一致するすべてのエントリを削除しなければならない。
ここでは [RFC7234] で定義される network cache を扱っているが、これはユーザーエージェントがキャッシュするすべてではない。ベンダー固有のセクションでどこまで曖昧にできるか?たとえば、Chrome はプリレンダページ、スクリプトキャッシュ、WebGL シェーダーキャッシュ、WebRTC の諸要素、アドレスバー候補キャッシュ、表現でないネットワーク関連のさまざまなもの(HSTS/HPKP, SCDHなど)もクリアする。おそらく [STORAGE] でより明確になるかもしれない?
4.2.4. origin の cookie をクリアする
origin(origin)が与えられた場合、ユーザーエージェントは以下のように origin の cookie をクリアする ことができる:
注: すべての 登録ドメイン の cookie を削除する。cookie
は同一生成元ポリシーを無視するためであり、特定のサブドメインのみの cookie をクリアした場合、アプリケーションが不定状態に陥るリスクがある。例えば
accounts.google.com と mail.google.com の双方にはサインイン状態を示す cookie が存在する。
注: このアルゴリズムはユーザーエージェントがcookie store([RFC6265] の 5.3 節に記載)を実装しており、host で cookie のリストを取得し、個々の cookie を削除できることを前提とする。
-
cookie list を cookie store から、
domain属性が domain-match となる registered の cookie セットとする。 -
cookie list の各 cookie について:
-
cookie を cookie store から削除する。
-
-
ユーザーエージェントが他の cookie 風ストレージをサポートしている場合、それも origins のうち、host の 登録ドメイン が registered であるものについて全てクリアしなければならない。
注: 例えば、ユーザーエージェントが Flash をサポートしている場合は、NPP_ClearSiteData でローカルストアオブジェクトもクリアされる。
-
[CHANNELID] の Channel ID と [TOKBIND] のバウンドトークンを、origins のうち、host の 登録ドメイン が registered であるものからクリアする。
-
authentication entries および proxy-authentication entries を、origins のうち host の 登録ドメイン が registered であるものについてクリアする。
bound tokens/IDs や HTTP 認証のクリアのプロセスは非常に曖昧。<https://github.com/w3c/webappsec-clear-site-data/issues/2>
4.2.5. origin の DOM からアクセス可能なストレージをクリアする
origin(origin)が与えられた場合、ユーザーエージェントは以下のように origin の DOM からアクセス可能なストレージをクリアする ことができる:
-
ユーザーエージェントの local storage areas [HTML] の各 area について:
-
ユーザーエージェントの session storage areas [HTML] の各 area について:
-
origin 用の databases [INDEXEDDB] の各 database について:
-
Delete database。
-
-
ユーザーエージェントの service worker registrations の各 registration について:
-
registration の scope URL の origin が origin の場合:
-
registration で
unregister()を実行する。
-
-
-
ユーザーエージェントの application caches の各 appcache について:
-
appcache の application cache group が、origin が origin である URL で識別される場合:
-
appcache を破棄する。
-
-
-
その他のスクリプトからアクセス可能なストレージについても、ユーザーエージェントはこの origin に関連付けられたすべてのデータを削除しなければならない。これには(但し限定されない)以下が含まれる:
-
origin の WebSQL データベース [WEBDATABASE]。
-
origin のファイルシステム [file-system-api]
-
プラグインデータ(例:Flash の NPP_ClearSiteData など)
-
5. セキュリティ考慮事項
5.1. 不完全なクリアリング
ストレージの種類を一つだけクリアした場合に、アプリケーションが不定状態に陥る可能性がある。これに対しては、すべてのストレージオプションをまとめてクリアし、ヘッダーをセキュア接続で配信することを必須とすることで、ある程度緩和ができる。
5.2. Service worker
Clear-Site-Data ヘッダーは、ネットワーク経由で取得されたレスポンスに対してのみ尊重されるべきであり、service worker から提供されるレスポンスには適用されてはならない。
service worker は、スコープ内のリソース要求(サードパーティ要求も含む)に対して任意のレスポンスを返せるため、Clear-Site-Data をサポートすると任意の origin のデータをクリアできる権限を与えてしまうことになる。
あるリクエストが service worker 宛に送られ、それが処理されず、service-workers mode を "none"
にして再実行されネットワークに送られた場合、そのレスポンスはネットワークレスポンスなのでハンドリングできる。前回の service worker からの応答取得は無関係である。
また、service worker アップデートはネットワークレスポンスとなるため、この制約の影響を受けない。これは §1.1.4 Kill Switch のユースケースのためにも重要である。
6. プライバシー考慮事項
6.1. Web 開発者がタイミングを制御
適切なタイミングで Clear-Site-Data
が発火される場合、ユーザーエージェントから機密データがクリアされることでユーザーのプライバシーやセキュリティが高まる。しかし、データクリアのトリガータイミングはウェブ開発者(ユーザーではない)が制御していることに注意。悪意のないサイト管理者であっても、ユーザは特定のタイミングでデータがクリアされることを保証できず、またどのデータ種類がクリアされるかもユーザが制御できない。
ユーザーが特定のタイミングでサイトデータが実際にクリアされたことを保証したい場合は、ユーザーエージェント自身によるデータ消去機能を利用すべきである。
最低限として、ユーザーエージェントは([RFC6919] の意味において)ウェブ開発者に提供している機能はユーザーにも提供「すべき」である。理想的には、プラットフォームレベルを超える機能(履歴のクリアなど)も提供することが望ましい。
6.2. ディスクに残るデータ
Clear-Site-Data
はユーザーエージェント内でクリアイベントを発火させるが、クリアイベントの後にユーザーのディスクの状態がどうなるかについては保証しにくい。とくに、すべてのサイトデータの痕跡をディスクから確実に消去する責任はユーザーエージェントにあるが、これは非常に難しい作業になりえる(たとえば仮想メモリなど)。
要するに、多くのユーザーエージェントは「ベストエフォート」で消去処理を実装しているが、完全な消去を保証できるわけではない。
ユーザーが本当にサイトデータがディスクに残らないことを保証したい場合、「意図的にディスクへデータを書き込まない」ことを約束しているブラウジングモード(Chrome の「シークレット」、IE の「InPrivate」など)を利用するのが最善である。これらのモードはより高い防御になるが、それでも完全には防げない制限がある。
7. IANA考慮事項
恒久的なメッセージヘッダーフィールドレジストリは以下の登録で更新する必要がある: [RFC3864]
7.1. Clear-Site-Data
- ヘッダーフィールド名
- Clear-Site-Data
- 対象プロトコル
- http
- ステータス
- standard
- 著者/変更管理者
- W3C
- 仕様ドキュメント
- 本仕様(§3.1 The Clear-Site-Data HTTP Response Header Field を参照)
8. 謝辞
Michal Zalewski がこのコンセプトのバリエーションを提案し、Mark Knichel が詳細化に協力した。