From 7bf4862a96c241f7b04569014fb5e567a283fd68 Mon Sep 17 00:00:00 2001 From: Mike Taylor Date: Tue, 29 Dec 2020 16:02:12 -0600 Subject: [PATCH 1/8] Issue #146 - Define "equivalence class" --- index.bs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/index.bs b/index.bs index 7cd55fe..fb1fb6c 100644 --- a/index.bs +++ b/index.bs @@ -422,8 +422,8 @@ Every {{WindowOrWorkerGlobalScope}} object has an associated equivalence class represents a group of browsers believed to be compatibile with each other. A shared + rendering engine may form an [=equivalence class=], for example. +

Getters

On getting, the {{NavigatorUAData/brands}} attribute MUST return [=this=]'s [=relevant global object=]'s [=WindowOrWorkerGlobalScope/brands frozen array=]. @@ -548,10 +551,10 @@ Let's examine a few examples: * In order to avoid sites from barring unknown browsers from their allow lists, Chrome could send a UA set that includes an non-existent browser, and which varies once in a while. - `"Chrome"; v="73", "NotBrowser"; v="12"` -* In order to enable equivalence classes based on Chromium versions, Chrome could add the rendering +* In order to enable [=equivalence classes=] based on Chromium versions, Chrome could add the rendering engine and its version to that. - `"Chrome"; v="73", "NotBrowser"; v="12", "Chromium"; v="73"` -* In order to encourage sites to rely on equivalence classes based on Chromium versions rather than +* In order to encourage sites to rely on [=equivalence classes=] based on Chromium versions rather than exact UA sniffing, Chrome might remove itself from the set entirely. - `"Chromium"; v="73", "NotBrowser"; v="12"` * Browsers based on Chromium may use a similar UA string, but use their own brand as part of the From 90b9b97267f332dc6d8f85a4d307ec65a586c9c7 Mon Sep 17 00:00:00 2001 From: Mike Taylor Date: Tue, 29 Dec 2020 16:02:56 -0600 Subject: [PATCH 2/8] Issue #146 - We're GREASEing a brand list, not the UA string --- index.bs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.bs b/index.bs index fb1fb6c..1b43cfc 100644 --- a/index.bs +++ b/index.bs @@ -530,20 +530,20 @@ One approach which might be advisable could be for each [=user agent=] to lock t the version number, then shifting platform and model information to something reasonably generic in order to reduce the fingerprint the header provides. -GREASE-like UA Strings {#grease} +GREASE-like UA Brand Lists {#grease} ---------------------- History has shown us that there are real incentives for [=user agents=] to lie about their branding in order to thread the needle of sites' sniffing scripts, and prevent their users from being blocked by UA-based allow/block lists. -Resetting expectations may help to prevent abuse of the UA string's brand in the short term, but -probably won't help in the long run. The world of network protocols introduced the notion of GREASE [[I-D.ietf-tls-grease]]. We could borrow from that concept to tackle this problem. [=User agents=]' [=user agent/brands=] containing more than a single entry could encourage -standardized processing of the `UA` string. By randomly including additional, intentionally +standardized processing of the [=user agent/brands=] list. By randomly including additional, intentionally incorrect, comma-separated entries with arbitrary ordering, they would reduce the chance that we ossify on a few required strings. @@ -570,8 +570,8 @@ of the header adhere to [=Structured Header=] parsing, by adding escaped double- semi-colons to those values. The purpose of this is to make non-compliant server implementations immediately aware that their parsing code is inadequate. -The value order in [=user agent/brands=] MUST change over time, the prevent receivers of the header -from relying on certain values being in certain locations in the string. +The value order in [=user agent/brands=] MUST change over time to prevent receivers of the header +from relying on certain values being in certain locations in the list. When choosing GREASE strategies, [=user agents=] SHOULD keep caching variance in mind and minimize variance among identical [=user agent=] versions. From 86691580bcab72241cd57a3d765b0c53ac3eb4f2 Mon Sep 17 00:00:00 2001 From: Mike Taylor Date: Wed, 30 Dec 2020 12:49:29 -0600 Subject: [PATCH 3/8] Issue #146 - Fix Processing model heading indentation --- index.bs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index 1b43cfc..5c8a5b4 100644 --- a/index.bs +++ b/index.bs @@ -411,13 +411,13 @@ Note: The high-entropy portions of the user agent information are retrieved thro Processing model {#processing} -------------- -

WindowOrWorkerGlobalScope

+

WindowOrWorkerGlobalScope

Each [=user agent=] has an associated brands, which is a [=/list=] created by running [=create brands=]. Every {{WindowOrWorkerGlobalScope}} object has an associated brands frozen array, which is a FrozenArray<NavigatorUABrandVersion>. It is initially the result of [=create a frozen array|creating a frozen array=] from the [=user agent=]'s [=brands=]. -

Create brands

+

Create brands

When asked to run the create brands algorithm, the [=user agent=] MUST run the following steps: 1. Let |list| be a [=/list=]. @@ -450,13 +450,13 @@ When asked to run the create brands algorithm, the [=user agent=] MUS An equivalence class represents a group of browsers believed to be compatibile with each other. A shared rendering engine may form an [=equivalence class=], for example. -

Getters

+

Getters

On getting, the {{NavigatorUAData/brands}} attribute MUST return [=this=]'s [=relevant global object=]'s [=WindowOrWorkerGlobalScope/brands frozen array=]. On getting, the {{NavigatorUAData/mobile}} attribute must return the [=user agent=]'s [=user agent/mobileness=]. -

getHighEntropyValues method

+

getHighEntropyValues method

The getHighEntropyValues(|hints|) method MUST run these steps: From 0c5a04be7d3f9ae987132f9ec8fa19de6799fea6 Mon Sep 17 00:00:00 2001 From: Mike Taylor Date: Wed, 30 Dec 2020 17:29:09 -0600 Subject: [PATCH 4/8] Issue #146 - Specify algorithms for arbitrary brands and versions --- index.bs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 5c8a5b4..e0bc6ff 100644 --- a/index.bs +++ b/index.bs @@ -435,7 +435,8 @@ When asked to run the create brands algorithm, the [=user agent=] MUS 4. The [=user agent=] SHOULD execute the following steps: 1. [=list/Append=] additional items to |list| containing {{NavigatorUABrandVersion}} objects, - initialized with arbitrary {{NavigatorUABrandVersion/brand}} and {{NavigatorUABrandVersion/version}} combinations. + initialized with arbitrary brand and + arbitrary version combinations. 2. Randomize the order of the items in |list|. @@ -450,6 +451,38 @@ When asked to run the create brands algorithm, the [=user agent=] MUS An equivalence class represents a group of browsers believed to be compatibile with each other. A shared rendering engine may form an [=equivalence class=], for example. +

Create arbitrary brand and version values

+ +To create an arbitrary brand, the [=user agent=] MUST run these steps: + + 1. Let |arbitraryBrand| be a [=/string=] composed of [=ASCII lower alpha=], [=ASCII upper alpha=], or 0x20 (SP), no + longer than twenty [=ASCII bytes=]. + 1. Let |arbitraryBrandList| be the result of splitting |arbitraryBrand| on ASCII + whitespace. + 1. Let |greaseyStack| be a [=stack=]. + 1. Let |greaseyChars| be the [=list=] of [=ASCII bytes=] « 0x20 (SP), 0x28 (left parenthesis), 0x29 + (right parenthesis), 0x2D (-), 0x2E (.), 0x2F (/), 0x3A (:), 0x3B (;), 0x3D (=), 0x3F (?), 0x5F (_) ». + 1. For each item of |arbitraryBrandList|, [=stack/push=] a randomly selected [=list/item=] from |greaseyChars| onto + |greaseyStack|. + 1. Let |greaseyBrandList| be a [=list=] and |index| be 0. + 1. While |greaseyStack| [=stack/is not empty=]: + 1. Let |item| be the result of popping from |greaseyStack|. + 1. Append |item| to |greaseyBrandList|. + 1. Append |arbitraryBrandList|[|index|] to |greaseyBrandList|. + 1. Increment |index| by 1. + 1. Return the result of stripping leading and trailing ASCII + whitespace from the [=concatenation=] of |greaseyBrandList| (with no separator). + + Note: [=Structured Headers=] allows for escaped 0x22 (\") and 0x5C (\\) inside a [=structured header/string=], but + these are known to not be web-compatible. + +To create an arbitrary version, return a [=/string=] that MUST match the format of the [=user agent=]'s +[=user agent/significant version=], but MUST NOT match the value. + +Note: User Agents may decide to send arbitrarily low versions to ensure proper version checking, and should vary them +over time. +

Getters

On getting, the {{NavigatorUAData/brands}} attribute MUST return [=this=]'s [=relevant global object=]'s [=WindowOrWorkerGlobalScope/brands frozen array=]. From 4180bd5eefbebb023de715c8484bfe059b772bbc Mon Sep 17 00:00:00 2001 From: Mike Taylor Date: Wed, 30 Dec 2020 17:30:17 -0600 Subject: [PATCH 5/8] Issue #146 - Clean up some whitespace and line lengths --- index.bs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/index.bs b/index.bs index e0bc6ff..f294b47 100644 --- a/index.bs +++ b/index.bs @@ -413,9 +413,12 @@ Processing model {#processing}

WindowOrWorkerGlobalScope

-Each [=user agent=] has an associated brands, which is a [=/list=] created by running [=create brands=]. +Each [=user agent=] has an associated brands, which is a [=/list=] created by running +[=create brands=]. -Every {{WindowOrWorkerGlobalScope}} object has an associated brands frozen array, which is a FrozenArray<NavigatorUABrandVersion>. It is initially the result of [=create a frozen array|creating a frozen array=] from the [=user agent=]'s [=brands=]. +Every {{WindowOrWorkerGlobalScope}} object has an associated brands frozen array, +which is a FrozenArray<NavigatorUABrandVersion>. It is initially the +result of [=create a frozen array|creating a frozen array=] from the [=user agent=]'s [=brands=].

Create brands

@@ -428,7 +431,8 @@ When asked to run the create brands algorithm, the [=user agent=] MUS 3. For each pair: 1. Let |dict| be a new {{NavigatorUABrandVersion}} dictionary, - with [=user agent/brand=] as {{NavigatorUABrandVersion/brand}} and [=user agent/significant version=] as {{NavigatorUABrandVersion/version}}. + with [=user agent/brand=] as {{NavigatorUABrandVersion/brand}} and [=user agent/significant version=] as + {{NavigatorUABrandVersion/version}}. 2. Append |dict| to |list|. @@ -448,8 +452,8 @@ When asked to run the create brands algorithm, the [=user agent=] MUS 5. Return |list|. -An equivalence class represents a group of browsers believed to be compatibile with each other. A shared - rendering engine may form an [=equivalence class=], for example. +An equivalence class represents a group of browsers believed to be compatibile with +each other. A shared rendering engine may form an [=equivalence class=], for example.

Create arbitrary brand and version values

From 0778dc3f7a3a236761d9bffdd41d4ad6267b64f0 Mon Sep 17 00:00:00 2001 From: Mike Taylor Date: Tue, 5 Jan 2021 16:49:17 -0600 Subject: [PATCH 6/8] Issue #146 - Only create a single arbitrary brand item --- index.bs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index f294b47..c6f6157 100644 --- a/index.bs +++ b/index.bs @@ -438,11 +438,11 @@ When asked to run the create brands algorithm, the [=user agent=] MUS 4. The [=user agent=] SHOULD execute the following steps: - 1. [=list/Append=] additional items to |list| containing {{NavigatorUABrandVersion}} objects, + 1. [=list/Append=] one additional [=list/item=] to |list| containing a {{NavigatorUABrandVersion}} dictionary, initialized with arbitrary brand and arbitrary version combinations. - 2. Randomize the order of the items in |list|. + 2. Randomize the order of the [=list/items=] in |list|. Note: One approach to minimize caching variance when generating these random components could be to determine them at build time, and keep them identical throughout the lifetime of the [=user agent=]'s significant @@ -599,8 +599,8 @@ Let's examine a few examples: - `"Chrome"; v="73", "Awesome Browser"; v="60", "Chromium"; v="73"` -[=User agents=] MUST include more than a single value in [=user agent/brands=], where at least one -of these values is an arbitrary value. +[=User agents=] MUST include more than a single value in [=user agent/brands=], where one of these values is an +arbitrary value. When adding arbitrary values to [=user agent/brands=], [=user agents=] MUST make sure that receivers of the header adhere to [=Structured Header=] parsing, by adding escaped double-quotes, commas and From 3f0daa8deab2aff46338dba3e3ba6d53dbd2545e Mon Sep 17 00:00:00 2001 From: Mike Taylor Date: Tue, 5 Jan 2021 17:09:16 -0600 Subject: [PATCH 7/8] Issue #146 - Remove requirement around GREASE syntax This is handled in the "create an arbitrary brand" algorithm. --- index.bs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/index.bs b/index.bs index c6f6157..61a8d0f 100644 --- a/index.bs +++ b/index.bs @@ -602,11 +602,6 @@ Let's examine a few examples: [=User agents=] MUST include more than a single value in [=user agent/brands=], where one of these values is an arbitrary value. -When adding arbitrary values to [=user agent/brands=], [=user agents=] MUST make sure that receivers -of the header adhere to [=Structured Header=] parsing, by adding escaped double-quotes, commas and -semi-colons to those values. The purpose of this is to make non-compliant server implementations -immediately aware that their parsing code is inadequate. - The value order in [=user agent/brands=] MUST change over time to prevent receivers of the header from relying on certain values being in certain locations in the list. From f9e8cf524bf109faefa7690c631385e0df927422 Mon Sep 17 00:00:00 2001 From: Mike Taylor Date: Thu, 7 Jan 2021 11:34:25 -0600 Subject: [PATCH 8/8] Issue #146 - Require 1 or more 0x20 (SP) bytes in arbitrary brand --- index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index 61a8d0f..6f75da9 100644 --- a/index.bs +++ b/index.bs @@ -460,8 +460,8 @@ each other. A shared rendering engine may form an [=equivalence class=], for exa To create an arbitrary brand, the [=user agent=] MUST run these steps: - 1. Let |arbitraryBrand| be a [=/string=] composed of [=ASCII lower alpha=], [=ASCII upper alpha=], or 0x20 (SP), no - longer than twenty [=ASCII bytes=]. + 1. Let |arbitraryBrand| be a [=/string=] composed of [=ASCII alpha=]. |arbitraryBrand| MUST contain one or more + 0x20 (SP) bytes and be no longer than twenty [=ASCII bytes=]. 1. Let |arbitraryBrandList| be the result of splitting |arbitraryBrand| on ASCII whitespace. 1. Let |greaseyStack| be a [=stack=].