オリジン間ストレージ

コミュニティグループ報告書草案,

このバージョン:
https://wicg.github.io/cross-origin-storage/
課題追跡:
GitHub
仕様内のインライン表示
編集者:
(Google)
(Thinktecture AG)
(Google)
参加:
GitHub WICG/cross-origin-storage (新しい課題, 未解決の課題)
コミット:
GitHub index.bs のコミット

概要

オリジン間ストレージ(COS)は、Web アプリケーションが AI モデル、WebAssembly モジュール、非常に普及している JavaScript ライブラリなどの 大容量ファイルを異なるオリジン間で保存および取得できる、コンテンツアドレス可能なキャッシュです。ファイルは URL ではなく暗号学的ハッシュによって識別されるため、あるオリジンによって一度取得された バイト単位で同一のリソースは、ユーザーエージェントが許可する他の任意のオリジンによって、再度ダウンロードすることなく再利用できます。キャッシュ内の存在を、ユーザーがどのサイトを訪問したかの推測に利用できないようにするため、 ファイルのオリジン間開示は、k-匿名性方式の人気度基準を満たすハッシュに限定されます。

この文書のステータス

この仕様は、Web Platform Incubator コミュニティグループによって公開されました。 これは W3C 標準ではなく、W3C 標準化過程上の文書でもありません。 W3C コミュニティ貢献者ライセンス契約 (CLA) では限定的なオプトアウトが認められており、その他の条件も適用されることに注意してください。 W3C コミュニティおよびビジネスグループについて詳しく学んでください。

1. はじめに

この節は非規範的です。

ストレージは通常、ユーザーのセキュリティとプライバシーを保護するためにオリジンごとに分割されます。これは適切な デフォルトですが、非常に大容量で、非常に普及し、一般に配布される限られた種類の リソース — AI モデル、WebAssembly モジュール、JavaScript ライブラリ、ゲームエンジン、大容量 Web フォント — には適していません。これらは、どのサイトが要求してもバイト単位で同一のファイルです。互いに無関係な 2 つのオリジンが 同じ 8 GB のモデルに依存する場合、オリジン分割ストレージではユーザーが そのモデルを 2 回ダウンロードして保持することを強制され、ユーザーの帯域幅、ストレージ、 バッテリー、そしてネットワーク全体を浪費します。

オリジン間ストレージ(COS)は、URL ではなく暗号学的ハッシュをキーとするコンテンツアドレス可能なキャッシュであり、ユーザーエージェントが、その利用をオプトインした オリジン間で、このようなリソースの単一の保存済みコピーを共有できるようにします。COS へのリソースの保存は、保存元オリジンによる 明示的なオプトイン操作であり、ユーザーエージェントは、本来そのリソースの読み取りを許可されるオリジンに対しても、 リソースの存在確認を控えることができます。§ 7 プライバシーおよび セキュリティに関する考慮事項を参照してください。

この仕様のエントリポイントは、requestFileHandle() メソッドであり、crossOriginStorageを介して公開されます。

const hash = {
  algorithm: 'SHA-256',
  value: '8f434346648f6b96df89dda901c5176b10a6d83961dd3c1ac88b59b2dc327aa4',
};
try {
  const handle = await navigator.crossOriginStorage.requestFileHandle(hash);
  const file = await handle.getFile();
  // ファイルを使用して何らかの処理を行う。
} catch (err) {
  if (err.name === 'NotFoundError') {
    // オリジン間ストレージ内に(開示可能な状態で)存在しないため、代わりにネットワークから取得する。
  }
}

この仕様は、FileSystemFileHandleFileSystemWritableFileStream、 およびファイルシステム標準 [FS] の関連インフラストラクチャを再利用しますが、単一オリジンの非公開またはユーザーに可視なファイルシステムではなく、 専用のオリジン間共有ファイルシステムに適用します。

この仕様は命令型 JavaScript API のみを定義します。関連する提案では、同じ基盤となるキャッシュを 他のホスト仕様に統合します — HTML の crossoriginstorage 属性( link および script)、 crossOriginStorage JavaScript import 属性、CSS の cross-origin-storage() <request-url-modifier>、および fetch() 用の crossOriginStorage RequestInit オプションです — それぞれは各自のホスト仕様で定義されています。次を参照してください: § 8 他の仕様との統合

2. 概念

2.1. ハッシュ

COS ハッシュは、次の項目を持つ構造体です。

アルゴリズム

[WEBCRYPTO]が認識するハッシュアルゴリズムの名前を表す文字列です。たとえば「SHA-256」です。

アルゴリズムによって生成されたダイジェストを小文字の 16 進数で符号化した文字列です。 「SHA-256」の場合、長さは 64 文字です。

algorithm 辞書メンバーは、その値空間が [WEBCRYPTO] のハッシュアルゴリズムが受け付ける名前の集合と完全に一致するにもかかわらず、HashAlgorithmIdentifierではなく、単純な DOMStringとして型付けされています。HashAlgorithmIdentifier(object or DOMString) であり、追加で object を受け付けます。このオブジェクトは [WEBCRYPTO] によって Algorithm形式の 辞書へ正規化され、呼び出し元は必要なアルゴリズムに追加パラメーターを渡せます (たとえば {name: "HMAC", hash: "SHA-256"})。ハッシュアルゴリズムはそのようなパラメーターを受け取らず、 アルゴリズムは単一の操作によって一度だけ消費されるのではなく、コンテンツアドレス可能な キーの一部として保存、比較、ラウンドトリップされます。また、この仕様の すべての例では単純な文字列が使用されています。ここで任意のオブジェクトを許可しても機能は増えず、 等価性とシリアル化を 不必要に複雑にするだけです。したがって、DOMString がこのフィールドにとって より限定的で、より適切な型です。

2 つのCOS ハッシュ値は、それらのアルゴリズム 値がASCII 大文字小文字不区別で一致し、かつそれらのが厳密に 等しい場合に、等しいとします。

注: 大文字小文字が規範的に制約されていないアルゴリズムとは異なり、 はすでに規範的に 小文字であるため(上記参照)、その比較はASCII 大文字小文字不区別の比較ではなく、単純な 文字列比較です。

コンテンツアドレス可能な ストアとは、そのエントリが URL や名前ではなく、 COS ハッシュ等価性をキーとするものです。バイト列が同一で、同じハッシュアルゴリズムを使用する 2 つのファイルは、 保存したオリジンの数や取得元 URL の数に関係なく、同じエントリです。

2.2. COS エントリ

各ユーザーエージェントには単一のCOS レジストリがあり、これはCOS ハッシュ値から COS エントリ構造体へのマップであり、オリジン間ストレージを使用するすべてのオリジンによって共有されます。 COS エントリは、次の項目を持ちます。

ハッシュ

COS ハッシュ

バイト列

null、またはバイト列であり、ハッシュアルゴリズム によるダイジェストが、ハッシュと等しいもの。ライターが 検証と 保存を完了するまでは null。

状態

pending」または「written」のいずれか。エントリーは「pending」として開始し、 バイト列が最初に設定されたとき、ちょうど一度だけ「written」になる。

保留中のライター数

初期値が 0 の負でない整数であり、未完了のライター、すなわち作成要求を完了するによって返された FileSystemFileHandle ハンドルのうち、その終了書き込みが まだ確定していないものを数える。検証して保存するにおいて、失敗した書き込みを安全に クリーンアップできるかどうかを判断するためにのみ使用される。§ 3.3 ファイルの作成と書き込みを参照。

オリジン

宣言された共有範囲。「*」(任意のオリジン)、オリジン文字列のリスト (それらのオリジンのみ)、または null(同一サイトのオリジンのみ)のいずれか。最初のライターによって設定され、 アップグレード可能だが、ダウングレードは不可能

保存元オリジン

このエントリーのバイト列の書き込みをそれぞれ少なくとも一度正常に完了したオリジン集合。ページの読み込みをまたいで永続化され、 時間の経過とともに増加する§ 5.2 退去で説明される場合を除き、減少することはない。保存元オリジンに含まれるオリジンは、 オリジンや、 エントリーのハッシュ公開ハッシュリスト (PHL)に掲載されているかどうかにかかわらず、 requestFileHandle() を介して常にそのエントリーのハンドルを取得できる。 § 3.4.1 元の保存者によるアクセスを参照。

ユーザーエージェントには、新しい並列キューを開始した結果である、関連付けられたオリジン間ストレージキューがあります。COS レジストリに対するすべての操作は、 このキューにエンキューされなければならず、それによって操作は エンキューされた 順序で実行され、互いに割り込むことがありません。

2.3. 公開ハッシュリスト

あるハッシュがオリジン間ストレージ内に存在することを確認する行為自体が、 ユーザーの閲覧履歴に関する情報を漏えいさせる可能性があります(§ 7.2 サイト間プロービングを参照)。これは、特にグローバルな 範囲を持つエントリに関するリスクです。オリジンリストまたは null であるエントリは、 保存元オリジンの明示的な選択によってすでに開示範囲が限定されていますが、「*」は、エントリを Web 上の任意のオリジンに公開する可能性があります。この特定のリスクを限定するため、「*」範囲のリソースは、 その保存元オリジン外のオリジンに対して、ハッシュが追加の独立したゲートを通過した場合にのみ 開示できます。このゲートは、ベンダー中立で実装定義COS ハッシュ 値の許可リストである公開ハッシュリストPHL)への登録です。ハッシュは、 k-匿名性方式の人気度基準を満たした場合にのみ公開ハッシュリストに登録されます。たとえば、一定数以上の独立した オリジンに、バイト単位で同一のものが存在する場合です。これにより、共有キャッシュ内にそのハッシュが存在することを確認しても、 個々のユーザーに関する情報にはなりません。

COS ハッシュ hashは、 hashがユーザーエージェントの現在の公開ハッシュリストのスナップショット内のエントリと 等しい場合に、公開ハッシュ リストに含まれるものとします。

Public Hash List の取得プロトコル、 更新頻度、データ形式、人気閾値、およびガバナンスは、この仕様の付属成果物として詳細に設計されており、 [URL] Standard のパブリックサフィックスリストが規範的な文ではなく付属データファイルであるのと同じ趣旨で、 このリポジトリの Public Hash List explainer を参照してください。この設計では、 Public Suffix List のベンダー横断的なローリングリリースの前例をモデルとして WHATWG によるガバナンスを提案し、 独立して裏付けられた普遍性を基準とする登録基準を採用しています。これは、上記で説明した k-anonymity スタイルの基準を 具体化したものであり、ユーザーエージェントがクエリごとに繰り返し確認するものではなく、ハッシュが登録される方法の一部として 一度だけオフラインで適用されます。この提案以外では、これらはまだ確立されていません。リスト自体の初期の非規範的なコードプロトタイプは、 このリポジトリの public-hash-list/implementation/ で維持されています — 実用的な 暫定的な配置場所です。専用のベンダー横断的なリポジトリは、PHL explainer で説明されているガバナンス目標として残されています。 この仕様は、特定の取得メカニズムやガバナンスモデルではなく、ハッシュが PHL 上にある かどうかだけに依存するため、その設計が どのように発展しても正しい状態を維持します。

3. CrossOriginStorageManager インターフェイス

[Exposed=(Window,Worker), SecureContext]
interface CrossOriginStorageManager {
  Promise<FileSystemFileHandle> requestFileHandle(
      CrossOriginStorageRequestFileHandleHash hash,
      optional CrossOriginStorageRequestFileHandleOptions options = {});
};

dictionary CrossOriginStorageRequestFileHandleHash {
  required DOMString value;
  required DOMString algorithm;
};

dictionary CrossOriginStorageRequestFileHandleOptions {
  boolean create = false;
  (DOMString or sequence<DOMString>) origins;
};

interface mixin NavigatorCrossOriginStorage {
  [SameObject, SecureContext] readonly attribute CrossOriginStorageManager crossOriginStorage;
};
Navigator includes NavigatorCrossOriginStorage;
WorkerNavigator includes NavigatorCrossOriginStorage;

Navigator およびWorkerNavigator オブジェクトには、関連付けられたCrossOriginStorageManager オブジェクトがあります。crossOriginStorage ゲッターの 手順は、thisに関連付けられたCrossOriginStorageManagerを返すことです。

CrossOriginStorageManager オブジェクトには、オブジェクトの作成時に this関連設定オブジェクトオリジンに設定される、関連付けられたオリジンがあります。

注: スクリプト自体に関する何らかの情報ではなく、関連設定オブジェクトからオリジンを取得することには、ワーカーについて明記する価値のある影響がある。 blob: URL から作成されたワーカーは、それを作成したコンテキストのオリジンを持つため、そのオリジンの Cross-Origin Storage ビューを完全に共有する。すなわち、そのようなワーカーが書き込んだものは、その作成元ページが読み戻すことができ、 ページが保存したものは、ワーカーが読み取ることができる。blob: URL 自体は独自のオリジンではなく、 それを取り消しても、ワーカーがそのビューから切り離されることはない。これに対して、data: URL から 作成されたワーカーは、不透明なオリジンを持つ。この仕様は現在、 requestFileHandle() が、呼び出し元のオリジンが不透明である場合に何を行うかを定義していない。 不透明なオリジンに関する COS リクエストを検証する際の規則が対象とするのは、 呼び出し元が 指定するオリジンであり、呼び出し元自身のオリジンではない。不透明なオリジンには、 保存 オリジン同一 サイトの比較のキーとして使用できる安定した識別情報がないため、 それに付与できる意味のあるものは何もない。

3.1. requestFileHandle() メソッド

handle = await navigator . crossOriginStorage . requestFileHandle(hash)

hash によって識別されるファイルが Cross-Origin Storage に存在し、呼び出し元 オリジンに開示可能である場合、そのファイルのハンドルを返す。それ以外の場合、これは "NotFoundError" DOMException で拒否される。 "NotFoundError" は、ファイルが Cross-Origin Storage に物理的に存在しないことを証明するものではない。§ 7.3 可用性ゲーティングを参照。呼び出し元は これを「代わりにこれをネットワークから取得する」として扱うことができる。

handle = await navigator . crossOriginStorage . requestFileHandle(hash, { create: true })

hash によって識別されるファイルを Cross-Origin Storage に書き込むために使用できるハンドルを返し、まだエントリーが存在しない場合は新しいエントリーを作成する。デフォルトでは同一サイトのオリジンに制限される。 呼び出し元は、エントリーがすでに 存在していたかどうかにかかわらず、ハンドルの createWritable() メソッドを介してファイルの完全な内容を書き込む必要がある。ユーザーエージェントはその時点で、書き込まれたバイト列のハッシュが hash になることを検証し、 そうでない場合は "DataError" DOMException で拒否する。この要件により、 オリジンが作成リクエストを、hash がすでに存在していたかどうかを判定するオラクルとして使用することを防ぐ。

handle = await navigator . crossOriginStorage . requestFileHandle(hash, { create: true, origins: "*" })

上記と同様だが、さらに、書き込み後は hash に対するリクエストが § 7.3 可用性ゲーティングを通過する任意のオリジンにエントリーを開示可能にする。

handle = await navigator . crossOriginStorage . requestFileHandle(hash, { create: true, origins: ["https://a.example", "https://b.example"] })

上記と同様だが、開示を列挙されたオリジンのみに制限する(呼び出し元 オリジン、およびすでに保存オリジンに含まれる任意のオリジンに加えて)。

requestFileHandle(hash, options) メソッドの 手順は次のとおりである:
  1. result新しい promise とする。

  2. realmthis関連 Realm とする。

  3. globalthis関連グローバルオブジェクトとする。

  4. originthis に関連付けられたオリジンとする。

  5. global に関連付けられた Document が存在する場合に、それが "cross-origin-storage" ポリシー制御機能の使用を許可されていない場合、次を行う:

    1. global を与えて、DOM 操作タスクソース上でグローバルタスクをキューに入れresult を "NotAllowedError" DOMException拒否する

    2. result を返す。

  6. validationFailure を、hash および options を与えてCOS リクエストを検証する処理を実行した結果とする。

  7. validationFailure が null でない場合:

    1. global を与えて、DOM 操作タスクソース上でグローバルタスクをキューに入れresultvalidationFailure拒否する

    2. result を返す。

  8. 次の手順を Cross-Origin Storage キューエンキューする:

    1. options["create"] が true の場合:

      1. resulthashoptionsglobal、および realm を与えて、作成リクエストを完了する処理を実行する。

    2. それ以外の場合:

      1. resulthashoriginglobal、および realm を与えて、読み取りリクエストを完了する処理を実行する。

  9. result を返す。

CrossOriginStorageRequestFileHandleHash hash および CrossOriginStorageRequestFileHandleOptions options を与えて COS リクエストを検証するには、null または TypeError を返す:
  1. hash["algorithm"] が [WEBCRYPTO] によって認識されるハッシュアルゴリズム 名でない場合、新しい TypeError を返す。

  2. hash["value"] が、hash["algorithm"] が "SHA-256" と ASCII 大文字・小文字を区別しない 一致であるときに、正規 表現 /^[0-9a-f]{64}$/ と一致しない場合、新しい TypeError を返す。

    注: 将来のハッシュアルゴリズムでは、 異なる期待ダイジェスト長を定義できる。この 仕様が規範的に制約するのは "SHA-256" のみであり、これは 例全体での 使用と一致する。

  3. options["origins"] が存在し、かつ "*" でない場合:

    1. candidatesoptions["origins"] とし、単一の文字列は、1 要素のリストとして扱う。

    2. candidatesサイズが ユーザーエージェントの オリジンリストの最大長より大きい場合、新しい TypeError を返す。

    3. candidates の各 candidate について反復する:

      1. candidate に対して基本 URL パーサーを実行した結果が 失敗である場合、または 解析された URL のオリジン不透明なオリジンである場合、新しい TypeError を返す。

  4. null を返す。

3.2. ファイルの読み取り

promise resultCOS ハッシュ hashオリジン origin、グローバルオブジェクト global、および Realm realm を与えて、読み取り リクエストを完了するには、次を行う:
  1. entry を、COS レジストリ内の、そのハッシュhash等しい COS エントリーが存在する場合はそのエントリーとし、それ以外の場合は null とする。

  2. entry が null でなく、かつ entry状態が "pending" の場合:

    1. global を与えて、DOM 操作タスクソース上にグローバルタスクをキューに入れresult を "NotAllowedError" DOMException拒否する

    2. 返る。

    注: 書き込み処理中のハッシュは、 意図的に存在しないハッシュと同じようには振る舞わない。これにより、呼び出し元が進行中の書き込みを真のキャッシュミスと誤認し、 単にそのファイルを書き込む目的だけで、非常に大きなファイルの冗長な同時ダウンロードを 開始することを防ぐ。§ 3.3 ファイルの作成と書き込みを参照。

  3. disclosableEntry を、entry および origin を与えて可用性 ゲーティングを適用する処理を実行した結果とする。

  4. disclosableEntry が null の場合:

    1. global を与えて、DOM 操作タスクソース上にグローバルタスクをキューに入れresult を "NotFoundError" DOMException拒否する

    2. 返る。

  5. handle を、realm 内で、その ロケーターCross-Origin Storage ファイルシステム内の disclosableEntry を指す、新しい FileSystemFileHandle作成した結果とする [FS]

  6. handleCOS オリジンorigin に設定する。

  7. handle読み取り可能を true に設定する。

    注: このハンドルはすでに可用性ゲーティングを適用する処理を通過しているため、呼び出し元オリジンには エントリーの バイト列を取得する権利がある。

  8. global を与えて、DOM 操作タスクソース上にグローバルタスクをキューに入れresulthandle解決する

COS エントリー または null の entry、および オリジン origin を与えて、COS 開示を決定するには、COS エントリーまたは null を返す:
  1. entry が null の場合、null を返す。

  2. 表明: entry状態は "written" である。

  3. originentry保存 オリジンに含まれる場合、entry を返す。

    注: 元の保存元、およびそのエントリーを 自身で正常に書き込んだ任意のオリジンは、 常にそれを読み戻すことができる。§ 3.4.1 元の保存元の アクセスを参照。

  4. entryオリジンが "*" の場合:

    1. entryハッシュPHL 上にない場合、null を返す。

      注: Public Hash List ゲートは、 ここでのみ、すなわちグローバルスコープのエントリーに適用される。これは、 そうでなければ開示が Web 上の任意のオリジンに及び得る唯一の 場合である。以下のリストスコープおよび同一サイトスコープの場合には適用されない。保存オリジンはそれらについてすでに 明示的で 範囲の限定された開示判断を行っており、それに加えて別個のグローバルな遍在性を要求すると、 通常の制限付き共有(§ 3.4 リソース可視性のアップグレードを参照)が、 しばしば専有リソースであるものに対する 無関係な公開キュレーションに依存することになる。§ 7.2 クロスサイトプロービングを参照。

    2. entry を返す。

  5. entryオリジンリストである場合:

    1. originシリアル化がその リストの項目である場合、 entry を返す。

    2. null を返す。

  6. 表明: entryオリジンは null である。

  7. originentry保存オリジンのいずれかの項目と同一サイトである場合、 entry を返す。

  8. null を返す。

COS エントリーまたは null の entry、および オリジン origin を与えて、可用性 ゲーティングを適用するには、COS エントリーまたは null を返す:
  1. disclosable を、entry および origin を与えてCOS 開示を決定する処理を実行した結果とする。

  2. disclosable が null の場合、null を返す。

  3. origindisclosable保存 オリジンに含まれる場合、disclosable を返す。

  4. ユーザーエージェントがこのリクエストにGREASE’ingを適用することを選択した場合、 null を返す。

  5. disclosable を返す。

3.3. ファイルの作成と書き込み

A FileSystemFileHandle created by 作成リクエストを完了するには、関連付けられた 要求オリジンがあり、これはハンドルへの 書き込みが正常に完了したときに、検証して保存するが エントリーのオリジンアップグレードしようとする値である。

COS エントリーを指すすべての FileSystemFileHandle には、さらに関連付けられた COS オリジン、すなわちそれを取得したオリジンと、関連付けられた 読み取り可能ブール値があり、これは getFile() がその特定のハンドルを介してエントリーのバイト列を開示できるかどうかを制御する。 これは、すでに 可用性ゲーティングを通過した読み取りリクエストを完了するによって返されるハンドルでは true であり、 作成 リクエストを完了するによって返されるハンドルでは、その同じハンドルについて検証して保存するが成功するまで false である。

注: これは意図的にエントリーではなくハンドルのプロパティである。 作成リクエストは、 エントリーがすでに存在し、すでに "written" であるかどうかにかかわらずハンドルを返す( 作成 リクエストを完了するを参照)。そのため、エントリー単位の規則では、任意のオリジンが requestFileHandle()create: true で呼び出し、自身が一度も書き込んでいないエントリーを直ちに読み取り、 オリジンPHL メンバーシップ、またはGREASE’ingを満たすことなく、その内容を知ることができてしまう。この 仕様のすべての開示制御は読み取り経路で適用されるため、エントリー単位でゲーティングすると、作成リクエストによって それらすべてを回避できてしまう。呼び出し元に最初に正しいバイト列を提供することを要求すれば、 作成によって取得したハンドルを介した読み取りが成功しても、呼び出し元がすでに持っていなかったものは何も開示されない。

promise resultCOS ハッシュ hashCrossOriginStorageRequestFileHandleOptions options、グローバルオブジェクト global、および Realm realm を与えて、作成 リクエストを完了するには、次を行う:
  1. requestedOrigins を、 options["origins"] を与えて要求 オリジンを正規化する処理を実行した結果とする。

  2. entry を、COS レジストリ内の、そのハッシュhash等しい COS エントリーが存在する場合はそのエントリーとし、それ以外の場合は null とする。

  3. entry が null の場合:

    1. entry を、ハッシュhashバイト列 が null、状態が "pending"、 オリジンrequestedOrigins、かつ 保存オリジンが空の集合である新しいCOS エントリーに設定する。

    2. 設定する: COS レジストリ[hash] を entry に。

  4. entry保留中のライター数を 1 増加させる。

    注: これは、呼び出し元が createWritable() を一度も呼び出さない場合や、結果として得られたストリームを一度も閉じない場合でも、handle を 未完了のライターとして追跡する。このように 放棄されたハンドルは entry に対して恒久的にカウントされる。これは、この仕組みが存在する以前に、 放棄された進行中の書き込みによって entry が恒久的に "pending" のままになっていたのとまったく同じである。 検証して 保存するを参照。

  5. handle を、realm 内で、その ロケーターCross-Origin Storage ファイルシステム内の entry を指す、新しい FileSystemFileHandle作成した結果とする [FS]

  6. handleCOS オリジンを、global関連設定オブジェクトオリジンに設定する。

  7. handle要求オリジンrequestedOrigins に設定する。

  8. handle読み取り可能を false に設定する。

    注: handle は、 entry がすでに存在していたかどうか、および すでに "written" であるかどうかにかかわらず返される。呼び出し元は引き続き handle を介して完全なファイルのバイト列を提供する必要がある。これにより、書き込みを以前から存在していたことの検出に使用できないようにし( § 7.2 クロスサイトプロービングを参照)、さらに、より寛容な オリジン 値のリクエストを受け入れる前に検証できるようにする。 § 3.4 リソース可視性のアップグレードを参照。

  9. global を与えて、DOM 操作タスクソース上にグローバルタスクをキューに入れresulthandle解決する

(DOMString または sequence<DOMString>) または undefined の origins を与えて、要求 オリジンを正規化するには、"*"、リストオリジン、または null を返す:
  1. origins存在しない場合、 null を返す。

  2. origins が "*" の場合、"*" を返す。

  3. list を « » とする。

  4. origins の各 candidate について反復する(単一の 文字列は、1 要素のリストとして 扱う):

    1. candidateOrigin を、candidate に対して基本 URL パーサー を実行して得られたオリジンとする。

      注: COS リクエストを検証する処理によって、各 candidate が 不透明でないオリジンとして解析されることはすでに確認されている。

    2. listcandidateOrigin含まない場合、candidateOriginlist付加する

  5. list を返す。

注: 後で既存のエントリーにマージする ときだけではなく、ここで重複を除去することにより、エントリーが 最初に作成された時点からオリジンには重複がなくなるため、それ以降に行われるすべての複製でも重複がない状態が維持される。

ロケーターCOS エントリーを指すハンドル上で createWritable() を呼び出すことで取得された FileSystemWritableFileStream が閉じられたとき [FS]、ユーザーエージェントは その終了操作の promise が履行される前に、以下の検証して保存する 手順を実行しなければならない。

注: これは、終了がどのように 引き起こされたかにかかわらず適用される。すなわち、明示的な close() 呼び出し、またはソースの終端に到達する pipeTo() 呼び出しであり、後者もデフォルトでは宛先を閉じる。[STREAMS]は、ストリームが閉じられる時点で両者を 区別せず、このアルゴリズムも区別しない。

閉じられたストリームのハンドルが指すCOS エントリー entry、完全に書き込まれたバイト列 bytes、および終了操作の 関連設定オブジェクトオリジン origin を与えたときの、検証して保存する 手順は次のとおりである:
  1. computedValue を、[WEBCRYPTO]に従い、 entryアルゴリズムによって指定された アルゴリズムを使用して計算した、bytes の小文字 16 進ダイジェストとする。

  2. computedValueentryと厳密に等しくない場合:

    1. 終了操作の promise を "DataError" DOMException拒否する

    2. 次の手順を Cross-Origin Storage キューエンキューする:

      1. entry保留中のライター数を 1 減少させる。

      2. entry状態が "pending" で、かつ entry保留中のライター数が 0 の場合、 entryハッシュCOS レジストリから削除する

        注: これにより、 失敗した書き込みは、恒久的に到達不能な "pending" エントリーを残すのではなく、自身の後始末を行う。同じハッシュに対する後続の requestFileHandle() 呼び出しは、他の ライターが未完了でなくなった時点で、エントリーをまったく認識せず、無期限の "NotAllowedError" ではなく、通常の "NotFoundError" を受け取る。 このカウントは、 同じハッシュについて同時に進行中の別のライター(たとえば、 2 つのタブがどちらもハッシュが存在しないことを確認し、それぞれ独立して書き込みを開始した場合)が、 まだ正常に書き込む可能性のあるエントリーを 削除することを防ぐ。そのライターがまだ未完了であるか、 すでに成功している場合、カウントがまだ 0 に達していないか、 entry状態がもはや "pending" ではないため、 この手順は何もしない。すでに "written" であるエントリーは、後から 何人のライターがそれを要求して失敗したかにかかわらず、この方法では決して削除されない。一度も正常に 書き込まれていないエントリーだけが対象となる。

    3. これらの手順を中止する。

  3. 次の手順を Cross-Origin Storage キューエンキューする:

    1. entryバイト列bytes に設定する。

    2. entry状態を "written" に設定する。

    3. origin がまだ存在しない場合、entry保存オリジン付加する

    4. entry保留中のライター数を 1 減少させる。

    5. entry とハンドルの 要求オリジンを与えて、リソース可視性をアップグレードする処理を実行する。

    6. ハンドルの読み取り可能を true に設定する。

      注: このハンドルだけが 読み取り可能になる。同じエントリーに対する別のハンドルで、 書き込みが行われていない別の作成リクエストから取得されたものは、読み取り不能のままである。

createWritable() が、 COS エントリを指す FileSystemFileHandle に対して呼び出された場合、 FileSystemWritableFileStream を生成しなければならず、その内容は空の状態から開始されなければならない。 これは、keepExistingData の値、および 対象エントリの状態に関係なく適用される。

注: [FS] では、それ以外の場合、keepExistingData は、既存ファイルの内容を ストリームの初期内容として設定するものと定義されている。ここでそれに従うと、呼び出し元は自身が一度も保持していなかったバイトの保存元 オリジンになることができてしまう。create 要求は、エントリが すでに存在するかどうかにかかわらずハンドルを返すため、呼び出し元は別のオリジンが保存したハッシュに対する writable を開き、何も 書き込まずに閉じることで、引き継がれたバイトのハッシュを要求された値に一致させることができる。これにより、 オリジン公開ハッシュリスト、および GREASE 処理が一度も参照されないまま読み取りアクセスが与えられることになる。これは、個別には許可されている2つの操作を組み合わせて成立する可用性 ゲーティングの回避である。同じ理由により、 検証して保存では、 create 要求のたびに完全な内容が必要となる。

注: したがって、書き込みを一度も行わずに閉じられた writable は 空のバイト列を保持することになり、これは呼び出し元が必要とするどのエントリについても 要求された値にはハッシュされないため、検証して保存は "DataError" DOMException で拒否する。これは、他の不一致の場合と同様である。その場合に 代わりにストレージまたは I/O の失敗を報告する実装は、検証結果を無関係な エラーの背後に隠すことになる。

ファイルシステム標準 [FS] では、依存する 仕様が FileSystemWritableFileStream の closing 手順に追加の書き込みごとの検証を組み込むための拡張ポイントをまだ定義していない。そのようなフックが存在するようになるまでは、この節で必要な動作を直接記述する。将来の 改訂では、[FS] と正式に統合されることが期待される。

3.4. リソースの可視性の拡張

COS エントリの可視性は 拡張できるが、縮小することはできない。

COS エントリ entry と、"*"、リストである オリジン、または null の requestedOrigins が与えられたときに、リソースの 可視性を拡張するには:
  1. requestedOrigins が null の場合、return する。

    注: origins を省略しても、既存の エントリの範囲が狭まることはない。これは同一サイトでの可用性を要求するだけであり、すべてのエントリはすでに少なくとも それと同程度の可用性を持っている。

  2. entryオリジンが "*" の場合、return する。

    注: すでにグローバルに利用可能なエントリを 後から書き込む者が制限することはできない。この 注記が適用され、requestedOrigins が "*" でない場合、ユーザーエージェントは 要求された制限が適用されなかったことを開発者に知らせるコンソール 警告を記録することが期待される。

  3. requestedOrigins が "*" の場合:

    1. entryオリジンを "*" に設定する。

    2. Return する。

  4. entryオリジンが null の場合:

    1. entryオリジンrequestedOrigins に設定する。

    2. Return する。

  5. merged を、entryオリジンクローンとする。

  6. requestedOrigins の各 candidateOrigin について反復する:

    1. mergedcandidateOrigin含む場合、continue する。

    2. mergedサイズ がユーザーエージェントのオリジンリストの最大長と等しい場合、 break する。

      注: 残りの candidateOrigin 値は、この拡張を失敗させるのではなく、この拡張から暗黙に破棄される — 書き込み自体はすでに成功している — が、ユーザーエージェントは エントリのオリジンリストが上限に達していることを示すコンソール警告を記録することが期待される。

    3. candidateOriginmerged付加する

  7. entryオリジンmerged に設定する。

注: 元の保存元だけでなく、新しいサイトも、 エントリのオリジンを拡張できる。ただし、 そのエントリのハッシュになるバイトも提供することが条件である。これは意図的である: あるハッシュに対応する正しいバイトをすでに保持している任意のサイトは、構造上、そのハッシュが何を表すかについて 元の保存元と同等に権威がある。

3.4.1. 元の保存元によるアクセス

オリジン書き込みを正常に完了した COS エントリ — すなわち、 エントリの保存元オリジンに含まれる任意のオリジン — は、その後いつでも requestFileHandle() を介してそのハンドルを取得できる。これは、エントリの オリジンの値とは無関係であり、 そのハッシュPHL 上にあるかどうかとも無関係である。 これは、オリジンが自身の保存したものには常にアクセスできる Cache API のモデルを反映している。

4. オリジン間ストレージファイルシステム

クロスオリジンストレージファイルシステムは、あらゆる オリジンのバケットファイルシステムやローカルファイルシステムアクセスのルートとは異なるファイルシステムルートであり、その エントリは、COS レジストリCOS エントリ項目と一対一に対応する。

クロスオリジンストレージファイルシステムは、[FS]の通常の呼び出しごとの 権限チェック モデルを使用しない。そこから取得されたすべてのFileSystemFileHandle は、スクリプトに返される前に § 3.2 ファイルの読み取りまたは§ 3.3 ファイルの作成と 書き込みによってすでに完全に認可されているため、そのようなハンドルに対して getFile() またはcreateWritable() を呼び出しても、 追加の権限プロンプトが発生することはない。

したがって、そのようなハンドル上のqueryPermission()およびrequestPermission()は、 プロンプトを表示できないため、 "prompt" を報告してはならない。それらは、作成要求によって取得されなかった ハンドルの書き込みモードについては "denied" を報告し、それ以外の場合は "granted" を報告しなければならない。

注: 書き込みは、ハンドルが 実際に欠いている可能性がある唯一の能力である。作成要求だけが、 書き込み可能なハンドルを生成するため、他の任意のハンドルの書き込みモードについて "granted" を報告すると、 createWritable() が拒否する能力を有すると主張することになる。読み取りは "granted" のままである。読み取り可能なハンドルを保持する呼び出し元は、そのハンドルを通じて読み取ることができるためである。要求しても、 表示するプロンプトもなく、許可を記録できる状態もないため、 どちらの結果も変更できない。

読み取り可能が false である COS エントリを指す FileSystemFileHandle に対してgetFile() を呼び出した場合、 "NotAllowedError" DOMException で拒否しなければならない。 これは、次の2つの異なるケースを対象とする:

ハンドルの読み取り可能が true になると、そのハンドルに対して呼び出されたgetFile() は、対象エントリのバイトを内容とするFile を返す。これは、 [FS]が、そのバイトを バイナリデータとして持つファイル エントリについてすでに定義している動作とまったく同じである。

COS エントリを指すFileSystemFileHandle は、 パス が、単一の文字列、すなわちエントリの COS ハッシュを含むリストであり、そのルートクロスオリジンストレージファイルシステムであるファイルシステムロケーターを持つ。

注: [FS]は、name を、ハンドルの ロケーターのパスの最後のパス成分として定義しているため、これはname を選択に委ねるのではなく確定する。それは ハッシュである。エントリにはそれ自体の名前がなく、ハッシュが唯一の識別情報であるため、 それを報告することで、空文字列なら失われる情報を保持できる。

エントリには名前も包含ディレクトリもないため、[FS]の構造的な機能の大半には 操作対象がない。識別性は例外であり、コンテンツアドレス指定されたエントリが 常に答えられる唯一の問いである。COS レジストリは、各COS ハッシュについて最大1つのCOS エントリしか保持しないため、2つの ハンドルは、それらのハッシュが等しい場合に限り同じエントリを指す。

COS エントリを指すFileSystemFileHandle に対してisSameEntry() を呼び出し、その引数も COS エントリを指し、かつ同じ オリジンによって取得されたものである場合、2つのハンドルのCOS ハッシュ項目が等しければ true を返し、そうでなければ false を返さなければならない。

注: これを拒否すると、ユーザー エージェントがすでに保持している情報を捨てることになる。

呼び出し元のオリジンが取得していない引数、 またはクロスオリジン ストレージファイルシステム以外のファイルシステムを指す引数を指定してisSameEntry() を呼び出した場合、拒否しなければならない。

注: その場合に false を返すと、 2つのハンドルが異なるエントリを指していると断言することになるが、 これは呼び出し元オリジンに検査する権限のないハンドルについての主張である。拒否は単に、 比較を行えなかったことだけを示す。

COS エントリを指す FileSystemFileHandle に対してmove()およびremove()を呼び出した場合、 "NotAllowedError" DOMException で拒否しなければならず、 エントリを変更せずに残さなければならない。

注: エントリは、その保存元 オリジン内のすべてのオリジンによって共有されるため、 削除を認めると、あるサイトが他のサイトの依存するデータを破壊できてしまう。削除は 追い出しおよびユーザー自身のストレージ制御に属する。名前変更や親の変更には 操作対象がない。エントリはそのCOS ハッシュによって名前付けされ、包含ディレクトリを持たないためである。

注: 執筆時点では、どちらのメソッドも[FS]にもファイルシステム アクセス API にも定義されていない (WICG/file-system-access#214)。 したがって、エラー名は、[FS]が エントリを削除する操作として定義しているremoveEntry() に従う。これは、readwrite アクセスが 許可されていない場合、アクセス結果のエラー名で拒否する。ここでは、存在しないのではなく拒否されるという解釈が正確である — これらの操作には意味があり、拒否される。

createSyncAccessHandle() については、ここで規則を定める必要はない。その手順は、ハンドルがバケットファイルシステム内にない場合は常に、 "InvalidStateError" DOMException で拒否し、 クロスオリジンストレージファイルシステムは、あらゆるオリジンのものとは異なるファイルシステムルートであるため、 [FS]がすでに 拒否とその名前の両方を決定している。

注: これは、この仕様が独立に定める場合にも 望ましい結果である。 FileSystemSyncAccessHandle は呼び出し元に書き込み可能なファイル記述子を渡すため、 エントリのバイトを、 それらが対応付けて保存されているCOS ハッシュと整合しない状態に 変更できてしまい、 そのエントリを開示可能な他のすべてのオリジンも同じバイトを読み取る。

4.1. ハンドルの転送

FileSystemFileHandleシリアル化可能オブジェクト [FS] であるため、 COS エントリを指すものは、別の環境設定オブジェクトに、たとえば postMessage(message, options) を使用して渡すことができる。 これは、 requestFileHandle() と並んで、そのようなハンドルを取得する第2の方法であるため、 ここでも制約される。

シリアル化手順は、COS エントリを指すFileSystemFileHandle について、value および serialized が与えられたとき、さらに次を行う:

  1. serialized.[[COSOrigin]] を valueCOS オリジンに設定する。

  2. serialized.[[COSMayRead]] を value読み取り可能に設定する。

逆シリアル化手順は、serializedvalue および realm が与えられたとき、さらに次を行う:

  1. serialized.[[COSOrigin]] が realm環境設定オブジェクトオリジン同一オリジンでない場合、 "DataCloneError" DOMException を投げる。

  2. valueCOS オリジンserialized.[[COSOrigin]] に設定する。

  3. value読み取り可能serialized.[[COSMayRead]] に設定する。

注: 同一 オリジンチェックがなければ、転送によって この仕様のすべての開示制御が一度に無効化されてしまう。読み取り可能が true のハンドルは、 すでに 可用性ゲーティングを適用それを要求したオリジンに対して通過している。これを別の オリジンに送信すると、そのオリジンについてオリジンPHL メンバーシップ、またはGREASE 処理が一度も評価されないまま、そのオリジンにエントリのバイトを渡すことになる。これは、 同様に同一オリジンの受信者に対してのみ有用であるハンドルについての、ファイルシステム標準の既存の扱いと一致する。

注: 読み取り可能は 再計算されるのではなくハンドルとともに移動するため、 書き込みが行われていない作成要求のハンドルは転送後も読み取り不能のままであり、 読み取り要求のハンドルは再度ゲーティングされることなく読み取り可能なままである。到着時に再ゲーティングすることは、 改善ではなく悪化となる。同じ ハンドルを転送することで、呼び出し元が可用性を繰り返し探ることができてしまうためである。

5. ストレージ管理

5.1. ストレージ制限

ユーザーエージェントは、単一のオリジンが他のオリジンのエントリを追い出そうとして キャッシュをあふれさせることを防ぐため、オリジン成功した書き込みを通じて COS レジストリに提供できる総バイト数に上限を 設けなければならない。具体的な上限は 実装定義である。オリジンの書き込みがその 上限を超える場合、ユーザーエージェントは 拒否し、 "QuotaExceededError" DOMException とし、コンソールに警告を記録するべきである。

注: エントリはコンテンツアドレス可能であるため、同じ バイトを同じハッシュの下に繰り返し書き込むオリジンは、最初の成功した書き込みを超えて追加のクォータを消費しない。§ 2.2 COS エントリを参照。

ユーザーエージェントはまた、実装定義オリジンリストの最大長を持つ。これは、 単一のオリジンリストに含めることができるオリジンの数を制限する 正の整数である。これは、リストが最初に指定されるとき(COS 要求を検証するを参照) と、後で既存のエントリにマージされるとき( リソースの可視性を拡張するを参照)の両方で適用されるため、単一の呼び出しでも、 時間の経過に伴う多数の呼び出しの累積的な影響でも、エントリのオリジンを無制限に 増大させることはできない。メモリ使用量を制限することに加えて、これはオリジンのリストが "*" の未宣言の代替として利用されることも防ぐ。§ 7.2 クロスサイトプロービングを参照。

この上限を超えた場合の処理は、これら2つの場所で異なる。2つの呼び出しが 操作の非常に異なる時点で発生するためである:

5.2. 削除

この節は非規範的である。

ストレージ逼迫時には、ユーザーエージェントはエントリCOS レジストリから追い出してよい。 たとえば、各エントリに最も最近アクセスした保存元オリジン全体にわたって 最終使用時刻が最も古いものを優先するポリシーを使用できる。ユーザーエージェントは、 ユーザーがどのファイルが保存されているか、各ファイルにどのオリジンがアクセスしたかを確認し、 エントリを手動で削除したり、すべてのクロスオリジンストレージデータを消去したりできる設定 UI を 提供することが期待される。

ユーザーがオリジンのサイトデータを消去した場合、ユーザーエージェントは、そのオリジンが含まれるすべての 保存元 オリジン集合からそのオリジンを削除するべきである。その削除後、COS エントリ保存元 オリジンが空になった場合、ユーザーエージェントはそのエントリを削除対象として考慮してよい。

5.3. 手動で追加されたエントリ

この節は非規範的である。

上記の設定 UI では、ユーザーがすでにディスク上に持っているファイルを直接 クロスオリジンストレージに追加できるようにしてよい — たとえば、どのウェブサイトとも無関係にダウンロードした AI モデルなど —​その際、 スクリプトが requestFileHandle() を呼び出すことはない。そのようなエントリには、 書き込みの帰属先となる要求元のオリジンが存在しないため、命令型 API だけでは答えられない2つの問題が生じる:

この方法で追加されると、状態が "written" のエントリは、それ以外の点では ウェブサイトが requestFileHandle() を介して書き込んだものと区別できない。同じ 可用性ゲーティングおよび可視性 拡張の規則が適用され、同じ オリジン値を持つ他の任意のエントリの場合とまったく同様である — エントリが最終的に "*" スコープになる場合のPHL 上にあるチェックも 含まれる。これは手動追加のデフォルトではあるが、唯一の可能な結果ではない。

5.4. 来歴メタデータ

この節は非規範的である。

COS エントリは、そのバイトが どこから来たのかについて、意図的に何も記録しない。識別情報は ハッシュだけである。同じバイトは、 いくつのオリジンがそれを保存したか、またはいくつの URL から取得されたかに関係なく同じエントリである (§ 2.2 COS エントリを参照)。URL はエントリではなく、ある 書き込み元による取得のプロパティであるため、複数のオリジンが書き込んだエントリについて1つを選ぶ非恣意的な方法はない。 URL はバイトのように検証可能でもない(§ 7.1 リソースの完全性を参照)。 また、パスやクエリ文字列は特定のドキュメント、 アカウント、またはセッションを識別できるため、保存元 オリジン内の粗粒度なオリジン値よりも、ユーザーの閲覧についてかなり多くの情報を含む。 したがって、それをエントリに記録すると、高エントロピーなシグナルが、 オリジン§ 7.3 可用性 ゲーティングが課すために存在する開示制限を迂回することになる。

それを求める動機自体はそれでも現実的である。§ 5.2 追い出しで説明した 設定 UI で数ギガバイトのファイルを確認しているユーザーも、 requestFileHandle() 呼び出しが失敗した理由をデバッグしている開発者も、そのファイルが どこから来たのかを知りたいだろう。ユーザーエージェントは、エントリと並行して実装内部の来歴記録を保持することで、 これに対応してよい — たとえば、その保存元オリジンのそれぞれが バイトを取得した URL とその時刻 — ただし、その記録をエントリの一部ではなくユーザーエージェントの状態として扱うことを条件とする:

このような記録はコンテンツから見えないため、ユーザーエージェントがそれを保持するかどうか、およびどの程度 保持するかは、完全に実装に委ねられる。この仕様にはそれに依存するものは何もなく、その 存在または不在をサイトが検出することはできない。

6. 権限ポリシーとの統合

この仕様は、文字列 "cross-origin-storage" によって識別されるポリシー制御機能 [permissions-policy]を定義する。 その既定の許可リストは self である。

この機能を使用することを許可されていないDocumentでは、そのDocumentから(または所有者がそのDocumentである worker から)行われるすべての requestFileHandle() 呼び出しが、ハッシュの検証、レジストリの検索、または書き込みが行われる前に、"NotAllowedError" DOMException で拒否される。

7. プライバシーおよびセキュリティに関する考慮事項

この節は、RFC 2119 のキーワードを使用する箇所を除き、非規範的です。リポジトリ内の セキュリティおよびプライバシー質問票も参照してください。

7.1. リソースの完全性

すべてのCOS エントリは暗号学的ハッシュをキーとし、その バイトはそのハッシュに対して検証される( § 3.3 ファイルの作成と書き込みを参照)。したがってサイトは、 requestFileHandle() を通じて取得したファイルが、hash を自身で取得した場合に得られるものと 完全に同じバイトを持つことを確信できる。開発者はクロスオリジンストレージの内容を列挙することも、 そのハッシュをすでに知っていないファイルにアクセスすることもできない。

COS ハッシュは秘密ではない。それは コンテンツ識別子であり、すでにファイルを持っている者なら誰でも簡単に計算でき、 この仕様が対象とする種類の広く配布される リソースについては日常的に公開情報となっている — たとえば、モデルやライブラリの リリースとともに公開される。したがって、ハッシュを知っていればエントリを検索するには十分だが、ケイパビリティ URL やベアラートークンとは異なり、それ自体ではアクセスを許可しない。検索が成功するかどうかは、ハッシュがたまたま 非公開のままだったかどうかではなく、完全にオリジン§ 7.3 可用性ゲーティングによって決定される。 開発者は、未公開のハッシュをアクセス制御メカニズムとして扱ってはならない。特定のファイルに関心を持つ 攻撃者は、そのハッシュを推測する必要はなく、ファイル 自体を入手するだけでよい(§ 7.2 クロスサイトプロービングを参照)。

7.2. サイト間プロービング

リソースが限られた一部のサイトでしか使用されていない場合、そのリソースがクロスオリジンストレージに 存在することを知ることができる攻撃者は、ユーザーがそれらのサイトのいずれかを訪問した可能性が高いと推測できる。 requestFileHandle() は存在を知るための仕組みであるため、各呼び出しは 実質的にはプローブである。この仕様にある 2 つの独立した仕組みにより、プローブが 知ることのできる範囲が制限される:

最初の箇条書きが成り立つのは、「選択されたオリジンの集合」が Web より有意に小さいままである場合に限られる。 origins の形式には、呼び出し元が 非常に多数のオリジンを列挙することを妨げるものはない — たとえば、公開されている トップサイトのランキングから組み立てたリストなど — これは、"*" のみが必要とする 意図的かつ明示的なオプトインを回避しながら、機能的にはグローバルな開示に近似することになる。オリジンリストの最大 長§ 5.1 ストレージ制限を参照)がこれを制限する。真の 複数プロパティのユースケース (共通の管理下にある少数の関連オリジン)を収容するには十分小さく、それでも「すべてのオリジン」の意味のある近似には はるかに及ばない上限にすることで、オリジンの制限付きオリジン形式が "*" の未宣言の代替として利用されることを防ぐ。

ユーザーエージェントはさらに、単一のオリジンからの requestFileHandle() の繰り返し呼び出しをレート制限するか、その他の方法でスロットリングするべきであり、 プローブ対象のハッシュがPHL 上にあるかどうかにかかわらず、 プローブの試みを識別してブロックするために、オンデバイスのヒューリスティクス (たとえば、ユーザーごとに生成されているように見えるハッシュに対するリクエストのパターンを検出すること)を適用してもよい。

§ 8 他の仕様との統合にあるホスト統合のいずれかによって実行される検索も、 ページにエラーが表示されないにもかかわらず、同様にプローブです。サイトは、 自身のサーバーがフォールバック要求を受信したかどうかを観測でき、これはここでの「見つからない」 という結果が持つものと同じ単一ビットを伝えます。このような検索は、この仕様のゲートが開示しない ものを何も開示せず、それらのゲートは変更なく適用されます。ただし、レート制限が有効なのは、 それらのサーフェスからの検索が requestFileHandle() 呼び出しと併せてカウントされる場合に限られます。なぜなら、 スクリプト可能な統合は、それらを同じように容易にループ内で発行できるためです。

7.3. 可用性ゲーティング

requestFileHandle() による読み取りが、保存元 オリジン外のオリジンから成功するかどうかは、要求元オリジンが エントリを読み取ることを許可されているかどうかに常に依存し、これはオリジンによって決まる。"*" スコープのエントリでは、これとは別の 独立した問題も適用される。すなわち、ユーザーエージェントがそのエントリがそもそも 存在することを開示する意思があるかどうかであり、これはPHL メンバーシップおよびGREASE 処理によって決まる。そのようなエントリでは両方が 成立しなければならない。リストまたは同一サイトスコープのエントリでは、最初の問題だけが適用されるが、 GREASE 処理によって、オリジンが本来 許可する開示が抑制されることはある。規範的アルゴリズムについては§ 3.2 ファイルの読み取りを参照。したがって、"NotFoundError" は、リソースが存在しないことの 証拠ではない。リソースが存在しない、要求元 オリジンが対象範囲外である、"*" スコープのリソースのハッシュが PHL 上にない(まだ、または今後も)、あるいは GREASE 処理が真陽性を抑制したことを意味する可能性がある。開発者は "NotFoundError" を 「ネットワークにフォールバックする」より具体的な意味として扱ってはならない。

注: "*" スコープのエントリの開示は、 現在のコンテキストでサードパーティ Cookie を設定または読み取ることができる要求元 オリジンにさらに制限される。そのような エントリは、サードパーティ Cookie を利用できないオリジンには、 PHL メンバーシップに関係なく開示されない。これは、PHL メンバーシップだけでは塞げない抜け穴を塞ぐ。攻撃者は、 個別には通常の PHL 対象となり得るリソースのうち、どの部分集合を書き込むかを選択することで、クロスサイト識別子を 構築できる。そして、その結果生じるプローブが通常のトラッキング Cookie よりも多くの情報を与えるかどうかを決める要因は、 サードパーティ Cookie を利用できるかどうかである。

7.4. GREASE の適用

ユーザーエージェントは、GREASE を適用してもかまいません(ランダムな拡張を生成して 拡張性を維持する)。これは、§ 7.3 可用性ゲーティングが本来開示を 許可する場合でも、開示可能なエントリが存在しないかのように時折応答することです。これによりノイズが加わり、 サイトが実際の不存在と、プライバシーを目的とする偽陰性を区別しにくくなります。これは、 UA クライアント ヒントで適用される手法に似ています。

GREASE を適用するユーザーエージェントは、対象エントリのサイズに応じた適切な判断を行わなければなりません。 小さいエントリでは、ネットワーク取得へのフォールバックが低コストであるため、時折生じる偽陰性は妥当なプライバシー上のトレードオフです。 ユーザーエージェントは、誤った再ダウンロードのコストが得られるプライバシー上の利益に明らかに不釣り合いとなるサイズのエントリに対して、 GREASE を適用してはなりません。たとえば、ギガバイト規模の AI モデルの重みです。この場合、偽陰性によって、 安価な再取得ではなく、完全で観測可能かつ高コストな再ダウンロードが強制されるためです。

7.5. フィンガープリンティング

攻撃者がオリジン間ストレージのプロービングから抽出できる情報は、プローブ対象リソースの人気度によって制限されます。 一般的な AI モデルや広く使用される JavaScript ライブラリなど、非常に人気の高いリソースをユーザーが持っていることを知っても、 ユーザーがそれを使用する多数のサイトのいずれかを訪問したことしか分かりません。一方、まれまたは一意のリソースを持っていることを知ると、 はるかに多くの情報が得られます。ユーザーエージェントは、ハッシュがユーザーごとに意図的に一意になるように見えるリソースを検出するため、 端末上のヒューリスティックを適用することが想定されます。たとえば、単一サイトによってしか書き込まれていないハッシュや、 異常な頻度で要求されるハッシュです。そして、公称上の PHL ステータスに関係なく、そのようなパターンをプロービング試行として扱うことが想定されます。

8. 他の仕様との統合

この節は非規範的です。

ここで定義されるCOS レジストリには、 requestFileHandle() を直接経由することなく、4つのホスト統合からもアクセスできる。それぞれの 統合は、この文書ではなく、それぞれのホスト仕様で定義される。この 仕様では、それらの統合が基盤として使用することが期待される共通の基礎概念(COS ハッシュCOS エントリ可用性ゲーティング、および公開ハッシュリスト)のみを定義する。

説明のためだけに、同じグローバルに共有されるリソースを、4つの各形式を通じて クロスオリジンストレージにオプトインする例を以下に示す:

<script src="popular-library.js" integrity="sha256-abc123..." crossoriginstorage="*"></script>
import data from "popular-resource.ext" with {
  integrity: "sha256-abc123...",
  crossOriginStorage: "*",
};
@font-face {
  font-family: "Popular Font";
  src: url("popular-font.woff2" integrity("sha256-abc123...") cross-origin-storage(*));
}
const response = await fetch("popular-resource.ext", {
  integrity: "sha256-abc123...",
  crossOriginStorage: "*",
});

これらのスニペットは説明のためだけのものである。この構文はいずれもこの仕様では定義されておらず、 制限された非 "*" の origins 値をどのように表記するかを含め、各形式の正式な文法は、 この文書ではなく、それぞれのホスト仕様に属する。表記は意図的に 異なっている。RequestInit メンバーは sequence<DOMString> を取ることができ、 origins と完全に一致する一方、属性値、 import 属性値、および CSS modifier 引数が保持できるのはテキストだけである。

4つの形式すべては、ネットワーク取得にフォールバックする前に、まず一致し、開示可能なエントリがあるか COS レジストリを参照し、 正常に取得され完全性が検証されたリソースを、他のオリジンによる再利用のため COS レジストリに保存するという処理モデルを共有することが期待される。 これは requestFileHandle() が行うこととまったく同じである。 これらの統合に関する議論は、このリポジトリの issue tracker ではなく、それらを採用する ホスト仕様の tracker で行われるべきである。

謝辞

Tab Atkins-Bittner、Yash Raj Bharti、Joshua Lochner からの貴重なフィードバック、 および Kenji Baheux と Kevin Moore からの貴重な着想またはアイデアに深く感謝します。

この仕様には、 ファイルシステムをモデルとした内容が含まれます。同仕様は W3C ソフトウェア および文書ライセンスの下で利用できます。

適合性

文書の 規約

適合性要件は、 説明的な表明と RFC 2119 の用語を組み合わせて表現されます。 この文書の規範的な部分におけるキーワード「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、 「MAY」、および「OPTIONAL」は、 RFC 2119 の説明に従って解釈されます。 ただし、読みやすさのため、 この仕様ではこれらの語が常にすべて大文字で表記されるわけではありません。

明示的に非規範的と示された節、例、および注を除き、 この仕様のすべての文章は規範的です。[RFC2119]

この仕様の例は、「たとえば」という語で導入されるか、 class="example"を使用して 規範的な文章から分離されます。 次のようになります。

これは参考例の一例です。

参考注記は「注」という語で始まり、 class="note"を使用して 規範的な文章から分離されます。 次のようになります。

注、これは参考注記です。

索引

この仕様で定義される 用語

参照によって定義される 用語

参考文献

規範的参考文献

[DOM]
Anne van Kesteren. DOM 標準. 現行標準. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 言語仕様. URL: https://tc39.es/ecma262/multipage/
[FETCH]
Anne van Kesteren. Fetch 標準. 現行 標準. URL: https://fetch.spec.whatwg.org/
[FileAPI]
Marijn Kruisselbrink. File API. URL: https://w3c.github.io/FileAPI/
[FS]
Austin Sullivan. ファイルシステム標準. 現行 標準. URL: https://fs.spec.whatwg.org/
[HTML]
Anne van Kesteren; ほか. HTML 標準. 現行標準. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 標準. 現行標準. URL: https://infra.spec.whatwg.org/
[PERMISSIONS-POLICY]
Ian Clelland. Permissions Policy. URL: https://w3c.github.io/webappsec-permissions-policy/
[RFC2119]
S. Bradner. 要求レベルを示すために RFC で使用する キーワード. 1997年3月. 現行の最良慣行. URL: https://datatracker.ietf.org/doc/html/rfc2119
[URL]
Anne van Kesteren. URL 標準. 現行標準. URL: https://url.spec.whatwg.org/
[WEBCRYPTO]
Daniel Huigens. Web Cryptography レベル 2. URL: https://w3c.github.io/webcrypto/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 標準. 現行 標準. URL: https://webidl.spec.whatwg.org/

非規範的参考文献

[SRI]
Frederik Braun. サブリソース 完全性. URL: https://w3c.github.io/webappsec-subresource-integrity/
[STREAMS]
Adam Rice; et al. Streams 標準. 現行 標準. URL: https://streams.spec.whatwg.org/
[UA-CLIENT-HINTS]
User-Agent クライアントヒント. コミュニティ グループ報告書草案. URL: https://wicg.github.io/ua-client-hints/

IDL 索引

[Exposed=(Window,Worker), SecureContext]
interface CrossOriginStorageManager {
  Promise<FileSystemFileHandle> requestFileHandle(
      CrossOriginStorageRequestFileHandleHash hash,
      optional CrossOriginStorageRequestFileHandleOptions options = {});
};

dictionary CrossOriginStorageRequestFileHandleHash {
  required DOMString value;
  required DOMString algorithm;
};

dictionary CrossOriginStorageRequestFileHandleOptions {
  boolean create = false;
  (DOMString or sequence<DOMString>) origins;
};

interface mixin NavigatorCrossOriginStorage {
  [SameObject, SecureContext] readonly attribute CrossOriginStorageManager crossOriginStorage;
};
Navigator includes NavigatorCrossOriginStorage;
WorkerNavigator includes NavigatorCrossOriginStorage;

課題索引

Public Hash List の取得プロトコル、更新頻度、データ形式、人気閾値、およびガバナンスは、この仕様の付属成果物として詳細に設計されており、 [URL] Standard のパブリックサフィックスリストが規範的な文ではなく付属データファイルであるのと同じ趣旨で、 このリポジトリの Public Hash List explainer を参照してください。この設計では、 Public Suffix List のベンダー横断的なローリングリリースの前例をモデルとして WHATWG によるガバナンスを提案し、 独立して裏付けられた普遍性を基準とする登録基準を採用しています。これは、上記で説明した k-anonymity スタイルの基準を 具体化したものであり、ユーザーエージェントがクエリごとに繰り返し確認するものではなく、ハッシュが登録される方法の一部として 一度だけオフラインで適用されます。この提案以外では、これらはまだ確立されていません。リスト自体の初期の非規範的なコードプロトタイプは、 このリポジトリの public-hash-list/implementation/ で維持されています — 実用的な 暫定的な配置場所です。専用のベンダー横断的なリポジトリは、PHL explainer で説明されているガバナンス目標として残されています。 この仕様は、特定の取得メカニズムやガバナンスモデルではなく、ハッシュが PHL 上にある かどうかだけに依存するため、その設計が どのように発展しても正しい状態を維持します。
File System Standard [FS] は、依存する仕様が FileSystemWritableFileStream の 終了手順に追加の書き込みごとの検証を組み込むための拡張ポイントを、まだ定義していません。そのようなフックが存在するまで、 このセクションでは必要な動作を直接説明します。将来の改訂では、 [FS] と正式に統合されることが期待されます。