├── .github └── workflows │ └── autopublish.yml ├── .gitignore ├── .pr-preview.json ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── compile.sh ├── deploy.sh ├── deploy_key.enc ├── index.bs ├── reliability.md ├── tag-security-privacy-third-party-delegation.md └── w3c.json /.github/workflows/autopublish.yml: -------------------------------------------------------------------------------- 1 | # Create a file called .github/workflows/auto-publish.yml 2 | name: CI 3 | on: 4 | pull_request: {} 5 | push: 6 | branches: [main] 7 | jobs: 8 | main: 9 | name: Build, Validate and Deploy 10 | runs-on: ubuntu-20.04 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: w3c/spec-prod@v2 14 | with: 15 | GH_PAGES_BRANCH: gh-pages 16 | VALIDATE_MARKUP: false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | index.html 2 | -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.bs", 3 | "type": "bikeshed", 4 | "params": { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: false 3 | python: 4 | - "3.8" 5 | 6 | install: 7 | # Setup bikeshed. See https://tabatkins.github.io/bikeshed/#travis-ci 8 | - pip3 install bikeshed 9 | - bikeshed update 10 | 11 | script: 12 | - bash ./deploy.sh 13 | 14 | env: 15 | global: 16 | - ENCRYPTION_LABEL: "c80b4dc18b55" 17 | - COMMIT_AUTHOR_EMAIL: "yoav@yoav.ws" 18 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Web Platform Incubator Community Group 2 | 3 | This repository is being used for work in the W3C Web Platform Incubator Community Group, governed by the [W3C Community License 4 | Agreement (CLA)](http://www.w3.org/community/about/agreements/cla/). To make substantive contributions, 5 | you must join the CG. 6 | 7 | If you are not the sole contributor to a contribution (pull request), please identify all 8 | contributors in the pull request comment. 9 | 10 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 11 | 12 | ``` 13 | +@github_username 14 | ``` 15 | 16 | If you added a contributor by mistake, you can remove them in a comment with: 17 | 18 | ``` 19 | -@github_username 20 | ``` 21 | 22 | If you are making a pull request on behalf of someone else but you had no part in designing the 23 | feature, you can remove yourself with the above syntax. 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All Reports in this Repository are licensed by Contributors 2 | under the 3 | [W3C Software and Document License](http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document). 4 | 5 | Contributions to Specifications are made under the 6 | [W3C CLA](https://www.w3.org/community/about/agreements/cla/). 7 | 8 | Contributions to Test Suites are made under the 9 | [W3C 3-clause BSD License](https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html) 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Explainer 2 | 3 | Client Hints is collection of HTTP and user-agent features that enables 4 | privacy-preserving, proactive content negotiation with an explicit cross-origin 5 | delegation mechanism: 6 | 7 | * Proactive content negotiation at the HTTP layer (defined in the 8 | [IETF RFC](https://tools.ietf.org/html/rfc8942)) 9 | enables servers to request delivery of specific hints, in order to enable 10 | optimized and automated selection of resources based on a user's device, 11 | conditions and preferences, and lets clients decide which hint requests they 12 | want to grant, with per-hint and per-origin granularity. 13 | * Integration of said mechanism with web concepts (defined in this 14 | [specification](https://wicg.github.io/client-hints-infrastructure)) 15 | specification) enables browsers to benefit from content adaptation, and have it 16 | play nicely with current web restrictions (e.g. same-origin policy). 17 | * The opt-in nature of the mechanism enables browsers to advertise requested 18 | hint data (e.g. user agent and device characteristics) selectively to 19 | secure-transport origins, instead of appending such data on every outgoing 20 | request. 21 | * Origin opt-in applies to same-origin assets only and delivery to cross-origin 22 | origins is subject to explicit cross-origin delegation via Feature Policy, 23 | enabling tight control over which cross-origin origins can access requested 24 | hint data. 25 | 26 | The goal of Client Hints is to **reduce passive fingerprinting** on the web 27 | while **enabling scalable and privacy preserving content adaptation** between 28 | client and server, via a standardized set of content negotiation primitives at 29 | the HTTP and user agent levels. 30 | 31 | This document outlines the Client Hints infrastructure, explains it at a high 32 | level and points to the various specification and draft proposals in which it 33 | is officially defined. It does not describe the various features and hints 34 | which rely on this infrastructure. They will be defined in their respective 35 | specifications. 36 | 37 | # The Client Hints infrastructure 38 | 39 | How can servers opt into receiving hints from the client? How should clients 40 | send those hints? And how should that be handled across origins? 41 | 42 | ## Opt-in mechanism 43 | 44 | In order to receive Client Hints, servers must opt-in by using the HTTP 45 | response headers described in the sections below. For security and privacy 46 | reasons, the opt-in must be received on the response of the top-level 47 | navigation, over a secure connection. 48 | Servers can similarly opt-in by using the headers' HTML equivalents, the 49 | `` HTML tag and its `http-equiv` attribute. 50 | 51 | ### `Accept-CH` 52 | 53 | The `Accept-CH` header enables servers to request specific hints from the 54 | browser. The header's value is a comma separated list, where each value in that 55 | list represents a request header hint that the server is interested in 56 | receiving. 57 | 58 | If a server's response to a navigation request includes the `Accept-CH: 59 | foo, bar` header, same-origin subresource requests on the page will include the 60 | `Sec-Foo: foo-value` and `Sec-Bar: bar-value` request headers unless the 61 | client has reasons to avoid sending that information to the server. 62 | 63 | ### `Delegate-CH` 64 | 65 | The `Delegate-CH` `` HTML tag enables top level frames to request specific hints 66 | from the browser. The header's value is a semi-colon separated list (akin to the 67 | [Permissions Policy syntax](https://www.w3.org/TR/permissions-policy/#algo-parse-policy-directive)), 68 | where each value in that list represents a request header hint that the server is interested in 69 | receiving. 70 | 71 | If the HTML response to a navigation request includes the `` tag, same-origin subresource requests on the page will include 73 | the `Sec-Foo: foo-value` and `Sec-Bar: bar-value` request headers, unless the 74 | client has reasons to avoid sending that information to the server. 75 | 76 | ## Same-Origin Policy 77 | 78 | There are three important restrictions on the opt-in mechanism description above: 79 | 80 | - opt-ins will only be granted when the opt-in headers are received with a 81 | top-level navigation resource 82 | - after the opt-in, hints will only be sent with same-origin requests 83 | - any `Delegate-CH` `` HTML tags injected by javascript will be ignored 84 | 85 | Why are these limitations important? 86 | 87 | As mentioned before, we don't want the mechanism to be used to increase 88 | fingerprinting on the web. The information that Client Hints provide should 89 | generally be available through Javascript APIs (see the 90 | [Privacy Considerations](#privacy-considerations) section for more details). 91 | 92 | That means that for *active* resources (e.g. HTML), Client Hints does not 93 | increase the active fingerprinting surface. Servers serving active resources 94 | can already exfiltrate the data that hints provide, via scripts, styles or 95 | certain elements (e.g. ``). Client Hints only provides servers 96 | with a more convenient and performant way to get that information for 97 | content-negotiation purposes and ensures that authors and user agents have 98 | ultimate control over which servers get what information. 99 | 100 | Client Hints also allow this information to be collected on *passive* 101 | sub-resources (e.g. images). We don't want cross-origin origins to be able to 102 | exfiltrate data about the client/user without explicit permission from the 103 | top-level origin. And we certainly don't want them to be able to exfiltrate it 104 | cross-origin, beyond the lifetime of the current navigation. 105 | 106 | Therefore, by default, Client Hints opt-in is only valid when delivered on 107 | top-level navigation requests before any scripts execute, and, by default, 108 | applies only to same-origin resources. Cross-origin requests must only receive 109 | hints when explicit permission is given by the top-level document's origin. 110 | 111 | ## Cross-origin hint delegation 112 | 113 | Why do we need cross-origin Client Hints? 114 | 115 | As the purpose of for client hints is to enable content negotiation at scale, and 116 | as many optimization services are offered over different origins than the main 117 | page's origin (e.g., CDNs, resource-specific hosting services, or dedicated, 118 | resource-specific, first-party sub-domains), cross-origin support is a vital 119 | part of Client Hints. 120 | 121 | In order to support these use-cases, we have defined delegation of Client Hints 122 | cross-origin, using a HTTP Permissions Policy or HTML Feature Policy. 123 | 124 | ### HTTP Example 125 | 126 | A server sending the following header `Permissions-Policy: ch-example=( 127 | "foo.com" "bar.com"), ch-example-2="foobar.org"` as part of a top-level navigation 128 | response will delegate the `example` hint to the "foo.com" and "bar.com" 129 | origins and `example-2` to the "foobar.org" origin. So, the client would know 130 | that it had explicit permission from the top-level origin to send these hints 131 | cross-origin, so that these cross-origin origins could perform content 132 | adaptation based on them. 133 | 134 | ### HTML Example 135 | 136 | A top level frame containing the following `` HTML tag: `` will delegate the 138 | `example` hint to the "foo.com" and "bar.com" origins and `example-2` to the "foobar.org" 139 | origin. So, the client would know that it had explicit permission from the top-level origin to 140 | send these hints cross-origin, so that these cross-origin origins could perform content 141 | adaptation based on them. 142 | 143 | ### Privacy implications 144 | 145 | Why is it privacy-safe for pages to delegate hints to certain cross-origin origins? 146 | 147 | Since we're treating Client Hints as an active fingerprinting equivalent, we 148 | are comfortable with the information it exposes to the top-level origin, as the same 149 | information is already freely available in the equivalent Javascript APIs. 150 | Similarly, cross-origin delegation is safe because top-level origin are already able to use 151 | other means (such as link decoration), to achieve the same information sharing 152 | cross-origin, in less convenient and performant ways. 153 | 154 | Further, the HTML delegation can only occur when the `` HTML tag is not injected 155 | via javascript, ensuring scripts cannot delegate hints in ways that relax the restrictions 156 | the top-level content author did not permit. 157 | 158 | In short, top-level origins already have the power to share information about the 159 | client cross-origin. Cross-origin delegation of Client Hints provides a 160 | cleaner pathway for that sharing, and ensures that top-level origin, and 161 | ultimately clients, are aware and in control of what is being shared with who. 162 | 163 | ## `Sec-` prefix 164 | 165 | Adding new request headers increases the risk that legacy server systems 166 | already use those values for a different purpose. Changing the request header 167 | values that such legacy systems receive may result in server bugs. 168 | 169 | While that risk is significantly mitigated by the opt-in mechanisms of Client 170 | Hints (as servers would be opting in to get Client Hints headers), we feel 171 | it is required to mitigate it even further. So, Client Hints request headers 172 | should be preceded by the `Sec-` prefix. 173 | 174 | The `Sec-` prefix also ensures that these headers are only generated by the 175 | browser and not added by potentially-malicious developers. That gives servers 176 | further guarantees when processing those headers. It may also enable us to 177 | simplify the related Fetch processing model, as it clearly indicates that these 178 | are headers that were added by the user agent. 179 | 180 | ## Caching considerations 181 | 182 | When adapting content to specific Client Hints request headers, servers should 183 | add the `Vary` header to their responses, with a value of each Client Hint 184 | header used, in order to indicate such adaptation to caches, and make sure that 185 | Client-Hint-negotiated resources are not cached using only their URL as the 186 | cache key. 187 | 188 | This is also the reason that each Client Hint is represented using a separate 189 | header. Ensuring that each hint has its own header reduces cache variance in 190 | responses that may rely on some hints, but not others. 191 | 192 | # Security and privacy considerations 193 | 194 | There are a few key mechanisms we already discussed that are part of the Client 195 | Hints infrastructure, which enable secure and privacy-preserving deployment 196 | of Client Hints: 197 | 198 | * Server opt-ins must be delivered on a top-level navigation request, over a 199 | secure connection. 200 | * Hints are only delivered with same-origin requests, over a secure connection. 201 | * If the top-level origin wants hints to be delivered to certain cross-origin origins, 202 | the top-level origin can explicitly delegate specific hints to specific origins. 203 | * Hints are `Sec-` prefixed, to provide servers with more confidence regarding 204 | the values they deliver, as well as to avoid legacy server bugs. 205 | 206 | Beyond that, when implementing Client Hints, browsers should make sure that 207 | certain privacy-related precautions are being taken: 208 | 209 | * Client Hint features should not be shipped unless there is a Javascript-based 210 | equivalent API, which enables developers access to the same data and is 211 | deemed privacy-safe to ship 212 | - This follows Extensible Web principles — we want the 213 | shipped features to be polyfillable (Even if `Sec-` headers cannot 214 | be added by developers) 215 | - As discussed above, from a privacy perspective, we consider Client Hints to 216 | be a potential active fingerprinting vector equivalent. Therefore, it is 217 | only safe to ship it with hints that provide information which is already 218 | available through other active fingerprinting means, such as a Javascript 219 | API. 220 | * Browsers should turn off hints when users choose to turn off Javascript 221 | - If the user has turned off Javascript, Javascript-based active 222 | fingerprinting vectors have been disabled. Since that could have been the 223 | user's intention when turning off scripting, browsers should similarly turn 224 | off Client Hints. 225 | * Browsers can choose to omit or to lie about certain Client Hints to increase 226 | their users' privacy 227 | - Browsers are free to take privacy-enhancing heuristics into account when 228 | deciding to respect the server's opt-in to receive them. Similar heuristics 229 | can also be used when deciding what values to send. 230 | 231 | # Motivation and trade-offs 232 | 233 | ## Proactive content negotiation and its benefits 234 | 235 | When choosing a solution that will provide alternative resources to the user's 236 | browser based on various factors, we are faced with a design dillema: Either 237 | the developer can provide the browser with a list of all potential URLs and let 238 | the browser choose the best one, or can use **content negotiation** and let the 239 | server pick the best-fit resource variant. 240 | 241 | The former option certainly has its place, and it is used successfully across 242 | the web in examples like ``, `srcset`, ``, etc. 243 | 244 | At the same time, there are some use-cases where it is not sufficient. 245 | Transformation and adaptation of the page's subresources in a manner that is 246 | independent from the page's markup can result in more scalable solutions, that 247 | don't have to be assimilated into markup related workflows. 248 | 249 | By decoupling the resource selection from markup, we can enable external 250 | services to perform those transformations automatically. We can also provide a 251 | wider range of resources, as offering more resources may result in some 252 | server-side costs, but those costs are not directly exposed to the user in the 253 | form of markup bloat. 254 | 255 | There are many potential dimensions by which we'd want the content adapted to 256 | the user: 257 | 258 | * Device characteristics 259 | - Screen dimensions 260 | - Screen density 261 | - Memory and CPU capabilities 262 | - Range of colors the screen can display 263 | * Browser characteristics 264 | - User Agent major or full version 265 | - Device model, OS version and platform 266 | - Supported formats and codecs 267 | * User preferences 268 | - Data-saving preferences 269 | - Preferred language 270 | * Network conditions 271 | - RTT 272 | - Effective bandwidth 273 | 274 | The list above is not necessarily exhaustive, but it can give us an idea as to 275 | why simply providing the browser with (possibly very long) list of resources 276 | which have been adapted across multiple dimensions of variability may not be 277 | practical, at least in some cases. 278 | 279 | ## An opt-in solution and its tradeoffs 280 | 281 | Client Hints requires that servers explicitly advertise and request sets of 282 | hints that they would like to receive. This makes such requests explicit and 283 | does not enable passive fingerprinting using those hints, which is one of the 284 | key and guiding requirements for Client Hints. 285 | 286 | Indiscriminately broadcasting user data carries other downsides, as well. Exposing 287 | all details and adaptation dimensions to all servers runs 288 | a risk of bloating request headers. There are many potential details that can 289 | be useful for content negotiation, and we expect that list to grow over time. 290 | Sending all of the hints all the time can quickly result in bloat, and make 291 | requests significantly larger than they should be. To avoid that, it is more 292 | efficient for servers to specifically request the headers that they would take into 293 | account, and for client to only send these hints with outgoing requests. 294 | 295 | Unfortunately, that decision doesn't come without tradeoffs. Client Hints as an 296 | opt-in mechanism currently means that content adaptation of the initial 297 | navigation request on the very first view is not possible, at least not without 298 | hacks. 299 | 300 | At the same time, for features which are critical for content negotiation of 301 | navigation requests, browsers may choose to send hints regardless of a server 302 | opt-in, when they deem that the information in question doesn't increase the 303 | passive fingerprinting surface. 304 | 305 | _Note:_ there may be other, out-of-band, opt-in mechanisms in the future that 306 | could enable delivery of hints on first navigation to new origins, such as 307 | Origin Policy. 308 | 309 | ## Privacy enhancing content negotiation 310 | 311 | Content negotiation is typically viewed as a mechanism that enables 312 | passive fingerprinting, by adding different bits of data to different user's 313 | requests, by default, and enabling servers to use those differences to tell 314 | users apart without leaving any trace of that activity. 315 | 316 | Client Hints’ opt-in mechanism enables us to avoid this problem, as 317 | servers need to tell the browsers which information they need, making any such 318 | use of fingerprinting detectable. 319 | 320 | But, Client Hints can also enable us to do more than that for user privacy, and 321 | turn passive-fingerprinting-enabling content-negotiation mechanisms (e.g. The 322 | `User-Agent` or `Accept-Language` request headers) into opt-in-only mechanisms. 323 | Restricting the amount of entropy that browsers send by default would 324 | effectively reduce the passive fingerprinting surface on the web, and Client 325 | Hints’ opt-in mechanism would enable browsers to keep closer tabs on entities 326 | that use that information for seemingly nefarious reasons. 327 | 328 | # Conclusion 329 | 330 | Client Hints provides a powerful content negotiation mechanism that enables us 331 | to adapt content to users' needs without compromising their privacy. It does 332 | that by requiring server opt-in, which guarantees that access to the 333 | information requires active and tracable action on the server's side. As such, 334 | the mechanism does not increase the web's current active fingerprinting 335 | surface. 336 | 337 | The Client Hints infrastructure can be further used to reduce the web's passive 338 | fingerprinting surface, by converting common use-cases for today's passive 339 | fingerprinting vectors (e.g. the `User-Agent` string) into Client Hints which 340 | require a specific opt-in. 341 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # So we can see what we're doing 4 | set -x 5 | 6 | # Exit with nonzero exit code if anything fails 7 | set -e 8 | 9 | # Run bikeshed. If there are errors, exit with a non-zero code 10 | bikeshed --print=plain -f spec 11 | 12 | # The out directory should contain everything needed to produce the 13 | # HTML version of the spec. Copy things there if the directory exists. 14 | 15 | if [ -d out ]; then 16 | cp index.html out 17 | fi 18 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e # Exit with nonzero exit code if anything fails 3 | 4 | SOURCE_BRANCH="main" 5 | TARGET_BRANCH="gh-pages" 6 | 7 | function doCompile { 8 | ./compile.sh 9 | } 10 | 11 | # Pull requests and commits to other branches shouldn't try to deploy, just build to verify 12 | if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then 13 | echo "Skipping deploy; just doing a build." 14 | doCompile 15 | exit 0 16 | fi 17 | 18 | # Save some useful information 19 | REPO=`git config remote.origin.url` 20 | SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:} 21 | SHA=`git rev-parse --verify HEAD` 22 | 23 | # Clone the existing gh-pages for this repo into out/ 24 | # Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply) 25 | # Delete all existing contents except .git (we will re-create them) 26 | git clone $REPO out 27 | cd out 28 | git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH 29 | find -maxdepth 1 ! -name .git ! -name . | xargs rm -rf 30 | cd .. 31 | 32 | # Run our compile script 33 | doCompile 34 | 35 | # Now let's go have some fun with the cloned repo 36 | cd out 37 | git config user.name "Travis CI" 38 | git config user.email "$COMMIT_AUTHOR_EMAIL" 39 | 40 | # If there are no changes to the compiled out (e.g. this is a README update) then just bail. 41 | if git diff --quiet; then 42 | echo "No changes to the output on this push; exiting." 43 | exit 0 44 | fi 45 | 46 | # Commit the "changes", i.e. the new version. 47 | # The delta will show diffs between new and old versions. 48 | git add -A . 49 | git commit -m "Deploy to GitHub Pages: ${SHA}" 50 | 51 | # Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc 52 | ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key" 53 | ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv" 54 | ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR} 55 | ENCRYPTED_IV=${!ENCRYPTED_IV_VAR} 56 | openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../deploy_key.enc -out ../deploy_key -d 57 | chmod 600 ../deploy_key 58 | eval `ssh-agent -s` 59 | ssh-add ../deploy_key 60 | 61 | # Now that we're all set up, we can push. 62 | git push $SSH_REPO $TARGET_BRANCH 63 | -------------------------------------------------------------------------------- /deploy_key.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WICG/client-hints-infrastructure/3f22f1167005ef36e4c492a7db5bfaf839769e8c/deploy_key.enc -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 | 2 | Title: Client Hints Infrastructure 3 | Shortname: ClientHintsInfra 4 | Level: 1 5 | Status: CG-Draft 6 | Group: WICG 7 | URL: https://wicg.github.io/client-hints-infrastructure 8 | Editor: Yoav Weiss, Google, yoav@yoav.ws, https://blog.yoav.ws 9 | Abstract: Specification of the Client Hints infrastructure and its integration with Fetch and HTML 10 | Markup Shorthands: markdown yes 11 | Repository: WICG/client-hints-infrastructure 12 | 13 | 14 | 15 | spec:html; type:element; text:link 16 | spec:html; type:element; text:script 17 | spec:fetch; type:dfn; for:/; text:fetch 18 | spec:fetch; type:dfn; for:Request; text:request 19 | spec:fetch; type:dfn; text:client 20 | spec:ServiceWorker; type:dfn; for:/; text: 21 | spec:url; type:dfn; for:url; text:origin 22 | spec:html; type:element; text:style 23 | spec:infra; type:dfn; text:user agent 24 | spec:html; type:dfn; text:navigable 25 | 26 | 27 | 28 | spec: HTML; urlPrefix: https://html.spec.whatwg.org/multipage/ 29 | urlPrefix: browsing-the-web.html 30 | type: dfn;text: populating a session history entry; url: populating-a-session-history-entry 31 | urlPrefix: semantics.html 32 | type: dfn; text: standard metadata names; url: standard-metadata-names 33 | spec: STRUCTURED-FIELDS; urlPrefix: https://www.rfc-editor.org/rfc/rfc8941.html#name- 34 | type: dfn 35 | text: sf-lists; url: lists 36 | spec: clear-site-data; urlPrefix: https://w3c.github.io/webappsec-clear-site-data/# 37 | type: dfn 38 | text: Clear-Site-Data Header; url: header 39 | 40 | 41 | 42 | { 43 | "PERMISSIONS-POLICY": { 44 | "authors": [ 45 | "Ian Clelland" 46 | ], 47 | "href": "https://w3c.github.io/webappsec-permissions-policy/", 48 | "publisher": "W3C", 49 | "title": "Permissions Policy" 50 | }, 51 | "CLIENT-HINT-RELIABILITY": { 52 | "authors": [ 53 | "David Benjamin" 54 | ], 55 | "href": "https://datatracker.ietf.org/doc/html/draft-davidben-http-client-hint-reliability", 56 | "publisher": "W3C", 57 | "title": "Client Hint Reliability" 58 | } 59 | } 60 | 61 | 62 | 66 | 67 | Introduction {#intro} 68 | ===================== 69 | 70 | Client Hints is collection of HTTP and user-agent features that enables 71 | privacy-preserving, proactive content negotiation with an explicit third-party 72 | delegation mechanism: 73 | 74 | * Proactive content negotiation at the HTTP layer enables servers to request 75 | delivery of specific hints, in order to enable optimized and automated 76 | selection of resources based on a user's device, conditions and preferences, 77 | and lets clients decide which hint requests they want to grant, with 78 | per-hint and per-origin granularity. 79 | * Integration of said mechanism with web concepts, defined in this document, 80 | enables browsers to benefit from content adaptation, and have it play nicely with 81 | current web restrictions (e.g. same-origin policy). 82 | * The opt-in nature of the mechanism enables browsers to advertise requested 83 | hint data (e.g. user agent and device characteristics) selectively to 84 | secure-transport origins, instead of appending such data on every outgoing 85 | request. 86 | * Origin opt-in applies to same-origin assets only and delivery to third-party 87 | origins is subject to explicit first party delegation via Permissions Policy, 88 | enabling tight control over which third party origins can access requested 89 | hint data. 90 | 91 | The goal of Client Hints is to **reduce passive fingerprinting** on the web 92 | while **enabling scalable and privacy preserving content adaptation** between 93 | client and server, via a standardized set of content negotiation primitives at 94 | the HTTP and user agent levels. 95 | 96 | Infrastructure definition {#definition} 97 | ========================= 98 | 99 | The specification of the Client Hints **infrastructure** is divided between the 100 | following specifications and proposals: 101 | 102 | * IETF [[!RFC8942]] 103 | - Provides the motivation for Client Hints. 104 | - Defines the `Accept-CH` response header, which servers may use to advertise 105 | support for certain Client Hints. 106 | - Provides both general guidelines, and formal requirements, about Client 107 | Hints’ impact on caching, security, and privacy. 108 | - Does *not* define any actual, particular hints – or say anything about how 109 | Client Hints works in web contexts. 110 | * Client Hints infrastructure - this document 111 | - Defines how web clients should process the `Accept-CH` headers sent by servers. 112 | - Defines the environment settings object state related to `Accept-CH`, 113 | which stores information about which servers should get which hints. 114 | - Defines how, and when, web clients should actually go about sending hints, 115 | based on the state of their environment settings object. 116 | - More specifically, it integrates the HTML web concepts with Fetch's 117 | algorithms to make sure that opted-in hints are added to requests for 118 | same-origin or delegated-to cross-origin requests. It also makes sure 119 | hints are removed from not delegated-to cross-origin requests after 120 | redirections. 121 | - Defines the `Critical-CH` response header, which servers may use to request a restart 122 | to include critical Client Hints missing in the initial load. 123 | - Integrates those concepts with the [[!HTML]] and [[!FETCH]] specifications, 124 | by patching various concepts there. 125 | * [[PERMISSIONS-POLICY|W3C Permissions Policy specification]] 126 | - In order to perform third party Client Hint delegation, Permissions Policy has 127 | been extended to control features within fetch requests (rather than just Documents). See [[permissions-policy#algo-should-request-be-allowed-to-use-feature]] 128 | * [[CLIENT-HINT-RELIABILITY|Client Hints Reliability]] 129 | - See Interaction with `ACCEPT_CH` frame. 130 | 131 | Environment settings object processing {#environment-settings-object-processing} 132 | ============== 133 | 134 | Client hints set 135 | 136 | A client hints set is a 137 | set of [=client hints token=]s. 138 | 139 | `Accept-CH` cache {#accept-ch-cache-definition} 140 | ---------------- 141 | 142 | An Accept-CH cache is owned by the user agent and is an [=ordered map=], 143 | [=keyed=] on origin (an [=url/origin=]), 144 | with a value of client hints set (a [=/client hints set=]). 145 | 146 | The Accept-CH cache can effectively act as an alternative cookie store, 147 | since sites can use each of the hints as a bit set on the client, and that information will be 148 | communicated to them on every request. As such, a user agent MUST evict that 149 | cache whenever the user clears their cookies or when session cookies expire. 150 | A user agent also MUST clear the Accept-CH according to the rules of the 151 | [=Clear-Site-Data Header=]. 152 | 153 | A site can clear the browser's `Accept-CH` cache for its origin by sending an empty `Accept-CH` header in a response. This sets the origin's [=/client hints set=] to an empty set. 154 | 155 | There MAY be multiple `Accept-CH` headers per-response and sf-lists can be split across lines as long as each line contains at least one token. 156 | 157 | Note: As the cache can only be modified by the top-level frame, it is considered to be partitioned. 158 | 159 | When asked to update the client hints set from cache given a |settingsObject|: 160 | 161 | 162 | Let |hintSet| be an empty [=ordered set=]. 163 | Let |originMatchingEntries| be the entries in the [=Accept-CH cache=] whose [=accept-ch-cache/origin=] is [=same origin=] with |settingsObject|'s [=environment settings object/origin=]. 164 | For each |entry| in |originMatchingEntries|, for each |token| in |entry|'s [=accept-ch-cache/client hints set=], [=set/append=] the |token| to |hintSet|. 165 | Let |frameHintSet| be the [=ordered set=] of hints requested by the `ACCEPT_CH` Frame (if any). 166 | For each |hint| in |frameHintSet| [=set/append=] the |hint| to |hintSet|. 167 | For each |hint| in |hintSet|, [=set/append=] |hint| to |settingsObject|'s [=environment settings object/client hints set=]. 168 | 169 | 170 | When asked to create or override the cached client hints set given a |settingsObject| and |response|: 171 | 172 | 173 | If |settingsObject| is a [=non-secure context=], abort these steps. 174 | Let |browsingContext| be |settingsObject|'s [=environment settings object/global object=]'s [=Window/browsing context=]. 175 | If the [=top-level browsing context=] does not equal |browsingContext|, abort these steps. 176 | If |response|'s `Accept-CH` header is not present, abort these steps. 177 | Let |hintSet| be an empty [=ordered set=]. 178 | For each |hint| in the result of parsing `Accept-CH` according to the header parsing rules, as a [=field-name=]: 179 | 180 | If |hint| is a [=client hints token=] add it to |hintSet|. 181 | 182 | Let |origin| be |response|'s [=url/origin=]. 183 | [=map/Set=] [=Accept-CH cache=][|origin|] to |hintSet|. 184 | 185 | 186 | `Critical-CH` {#critical-ch-algo} 187 | -------- 188 | 189 | If an [=url/origin=] is loaded and the server sets an `Accept-CH` header that 190 | lists hints not already in the current [=Accept-CH cache=] that means only 191 | subsiquent loads of that [=url/origin=] will include the hints. If it's 192 | critical that every load (including the first) has the requested Client Hints, 193 | then the server can set a `Critical-CH` header to request a restart. The 194 | `Critical-CH` header itself does not modify the [=Accept-CH cache=]. 195 | 196 | A restart will only occur when a hint in the `Accept-CH` header is both *not in* 197 | the [=Accept-CH cache=] and *in* the `Critical-CH` header. If hints listed in 198 | the `Critical-CH` header are already in the [=Accept-CH cache=] no restart is 199 | needed as they were sent. If hints listed in the `Critical-CH` header are not 200 | in the `Accept-CH` header a restart would not result in the hints being included 201 | anyway. 202 | 203 | The restart retries the entire navigation (including any prior redirects). 204 | 205 | There MAY be multiple `Critical-CH` headers per-response and sf-lists can be split across lines as long as each line contains at least one token. 206 | 207 | When asked if the user agent should restart loading the page for critical client hints given a |settingsObject| and |response|: 208 | 209 | 210 | If |settingsObject| is a [=non-secure context=], abort these steps. 211 | Let |browsingContext| be |settingsObject|'s [=environment settings object/global object=]'s [=Window/browsing context=]. 212 | If the [=top-level browsing context=] does not equal |browsingContext|, abort these steps. 213 | If |response|'s `Accept-CH` header is not present, abort these steps. 214 | If |response|'s `Critical-CH` header is not present, abort these steps. 215 | Let |missingHintSet| be an empty [=ordered set=]. 216 | For each |hint| in the result of parsing `Accept-CH` according to the header parsing rules, as a [=field-name=]: 217 | 218 | If |hint| is a [=client hints token=] add it to |missingHintSet|. 219 | 220 | Let |origin| be |response|'s [=url/origin=]. 221 | For each |hint| in [=Accept-CH cache=][|origin|]: 222 | 223 | Remove |hint| from |missingHintSet| if present. 224 | 225 | For each |hint| in the result of parsing `Critical-CH` according to the header parsing rules, as a [=field-name=]: 226 | 227 | If |hint| is in |missingHintSet| return `true`. 228 | 229 | Return `false`. 230 | 231 | 232 | `Delegate-CH` {#delegate-ch-algo} 233 | -------- 234 | 235 | There MAY be multiple `Delegate-CH` tags per-document and this algorithm is run once for each in the order of the appearance of the tags. 236 | 237 | Note: This metadata *appends* [=client hints token=]s to the [=environment settings object=]'s [=environment settings object/client hints set=]. It *does not* add those hints to the [=Accept-CH cache=]. 238 | 239 | 240 | Let |metaElement| be the <{meta}> element. 241 | If any <{link}>, <{style}>, or <{script}> elements have begun to execute, then return. 242 | If |metaElement| has no <{meta/http-equiv}> attribute, or if that attribute's value is not `delegate-ch`, then return. 243 | If |metaElement| has no <{meta/content}> attribute, or if that attribute's value is the empty string, then return. 244 | Let |settingsObject| be |metaElement|'s [=relevant settings object=]. 245 | If |settingsObject| is a [=non-secure context=], abort these steps. 246 | Let |browsingContext| be |settingsObject|'s [=environment settings object/global object=]'s [=Window/browsing context=]. 247 | If the [=top-level browsing context=] does not equal |browsingContext|, abort these steps. 248 | Let |permissionsPolicy| be |metaElement|'s node document's [=Document/permissions policy=]. 249 | Let |delegateCHValue| be the value of |metaElement|'s <{meta/content}> attribute. 250 | Let |policyDirective| be the result of running [[permissions-policy#algo-parse-policy-directive]] on |delegateCHValue| and the [=url/origin=] of the |metaElement|'s node document. 251 | For each |feature|->|allowList| of |policyDirective|: 252 | 253 | If |feature| is not a [=client hints token=], then continue. 254 | If |permissionsPolicy|[|feature|]'s [[PERMISSIONS-POLICY|permissions policy]] is `*`, then continue. 255 | Let |filteredAllowList| be an empty [=ordered set=]. 256 | For each |item| in |allowList|: 257 | 258 | If |item| is [=url/origin=] then [=set/Append=] |item| to |filteredAllowList|. 259 | 260 | [=set/Append=] |feature| to |settingsObject|'s [=environment settings object/client hints set=] and [=set/Append=] |filteredAllowList| to |permissionsPolicy|[|feature|]'s [[PERMISSIONS-POLICY|permissions policy]]. 261 | 262 | 263 | 264 | Issue(110): Clarify detection of <{link}>, <{style}>, or <{script}> element execution. 265 | 266 | Interaction with `ACCEPT_CH` frame {#interaction-with-accept-ch-frame} 267 | -------- 268 | 269 | The `ACCEPT_CH` frame is a way for Client Hints to be requested by a server 270 | during the TLS handshake of HTTP/2 and HTTP/3. The requested hints are *not* 271 | persisted in the [=Accept-CH cache=], but will be retrieved and merged when 272 | [=update the client hints set from cache=] is run. The full processing model 273 | is defined in [[CLIENT-HINT-RELIABILITY|Client Hints Reliability]]. 274 | 275 | There MUST be only one `ACCEPT_CH` frames per-connection. Additional frames will be ignored. 276 | 277 | Integration with HTML {#html} 278 | =========== 279 | 280 | This specification integrates with the [[!HTML]] specification by patching the algorithms below: 281 | 282 | Navigable {#navigable} 283 | ---------- 284 | 285 | Add a new field to [=navigable=]: 286 | 287 | A `Critical-CH` restart time {{DOMHighResTimeStamp}}, initially 0. 288 | This records the time the navigation was restarted to ensure required Client Hint 289 | headers will be sent. 290 | 291 | 292 | Navigation response {#navigation-response} 293 | ---------- 294 | 295 | At [=populating a session history entry=], in step 6 after substep 7 insert the following: 296 | 297 | Let |shouldRestartForCriticalClientHints| be `false`. 298 | If navigable's [=Critical-CH restart time=] is 0: 299 | 300 | Let |shouldRestartForCriticalClientHints| be the result of running [$should restart page for critical client hints$] with the [=relevant settings object=] and |response|. 301 | 302 | Run [$create or override the cached client hints set$] with the [=relevant settings object=] and |response| as inputs. 303 | If |shouldRestartForCriticalClientHints| then: 304 | 305 | Set navigable's [=Critical-CH restart time=] to the [=current high resolution time=]. 306 | Restart the initial navigation (before any redirects). 307 | 308 | If navigable's [=Critical-CH restart time=] is not 0: 309 | 310 | Set navigationParams's [=Critical-CH restart time=] to be navigable's [=Critical-CH restart time=]. 311 | 312 | 313 | 314 | Issue(154): Clarify how "Restart the initial navigation (before any redirects)" integrates with the HTML spec. 315 | 316 | At [=navigation params=], append the following: 317 | 318 | `Critical-CH` restart time 319 | a {{DOMHighResTimeStamp}} used for [=creating the navigation timing entry=] for the new Document. 320 | This records the time the navigation was restarted to ensure required Client Hint headers will be sent. 321 | 322 | 323 | 324 | Service Worker initialization {#service-worker-init} 325 | ----------- 326 | At set up a worker environment settings object, 327 | after step 6, add the following step: 328 | 329 | If worker global scope implements {{ServiceWorkerGlobalScope}}, then set settings object's [=environment settings object/client hints set=] to be a [=set/clone=] of outside settings' [=environment settings object/client hints set=]. 330 | 331 | 332 | Standard metadata names {#standard-metadata-names} 333 | ------------ 334 | For the section [=standard metadata names=], 335 | add a subsection named `delegate-ch` with the [=Delegate-CH|outlined explanation=]. 336 | 337 | Extending environment settings object {#extending-environment-settings-object} 338 | ------------- 339 | 340 | An [=environment settings object=] has a client hints set: a [=/client hints set=], initially the empty set, used for [=fetches=] performed using the [=environment settings object=] as a [=request=] [=client=]. 341 | 342 | 343 | Request processing {#request-processing} 344 | =========== 345 | 346 | When asked to append client hints to request with |settingsObject| and |request| as input, run the 347 | following steps: 348 | 349 | 350 | If |request| is a [=non-subresource request=] for a "sharedworker" or "worker" [=request/destination=], exit without appending any hints to the [=request/header list=]. 351 | Let |hintSet| be an empty [=/client hints set=]. 352 | Run [=update the client hints set from cache=] with |settingsObject|. 353 | For each [=client hints token=] |lowEntropyHint| in the registry's [=low entropy hint table=], [=set/append=] |lowEntropyHint| to |hintSet|. 354 | If |request|'s [=request/client=] is not null, then for each [=client hints token=] |requestHint| in 355 | |settingsObject|'s [=environment settings object/client hints set=], [=set/append=] |requestHint| to 356 | |hintSet|. 357 | For each |hintName| in |hintSet|: 358 | 359 | If |request| is not a [=navigation request=] for a "document" [=request/destination=]: 360 | 361 | Let |requestPermitsHint| be the result of running [[permissions-policy#algo-should-request-be-allowed-to-use-feature]] given |request| and |hintName|'s associated feature in [[#policy-controlled-features]]. 362 | If |requestPermitsHint| is `false`, then continue to next |hintName|. 363 | 364 | If the user agent decides, in an [=implementation-defined=] way (see [[#privacy]]), to omit this hint then continue. 365 | Let |value| be the result of running [=find client hint value=] with |hintName|. 366 | If the user agent decides, in an [=implementation-defined=] way (see [[#privacy]]), to modify |value| then do so. 367 | [=header list/append=] |hintName|/|value| to the [=request/header list=]. 368 | 369 | 370 | 371 | When asked to remove client hints from redirect if needed with |request| as input, run the following steps: 372 | 373 | 374 | For each hintToken in the list of [=client hints token=]s: 375 | 376 | If request's header list contains 377 | hintToken, then remove hintToken from |request|'s [=request/header list=]. 378 | 379 | 380 | 381 | Integration with Fetch {#fetch} 382 | ============== 383 | 384 | This specification integrates with the [[!FETCH]] specification by patching the algorithms below: 385 | 386 | In HTTP-network-or-cache fetch, within step 8, after substep 23, run [$append client hints to request$] with the [=relevant settings object=] and |request| as input. 387 | 388 | In [=HTTP-redirect fetch=], after step 11, run [$remove client hints from redirect if needed$] with |request| as input. 389 | 390 | In [=forbidden request-header=], to the list of headers within step 1, add `Save-Data`, `DPR`, `Device-Memory`, `Width`, and `Viewport-Width`. 391 | 392 | Feature Registry {#registry} 393 | ========== 394 | 395 | Note: This section contains feature-specific definitions. 396 | New features that rely on the Client Hints infrastructure need to add their respective definitions to this registry. 397 | User Agents can implement some of those features without implementing others. 398 | 399 | Client hints token {#client-hints-token-definition} 400 | ---------- 401 | 402 | A client hints token is a [=byte-lowercase=] representation of one of 403 | `Save-Data`, 404 | `Sec-CH-DPR`, 405 | `Sec-CH-Width`, 406 | `Sec-CH-Viewport-Width`, 407 | `Sec-CH-Viewport-Height`, 408 | `Sec-CH-Device-Memory`, 409 | `Sec-CH-RTT`, 410 | `Sec-CH-Downlink`, 411 | `Sec-CH-ECT`, 412 | `Sec-CH-Prefers-Color-Scheme`, 413 | `Sec-CH-Prefers-Reduced-Motion`, 414 | `Sec-CH-UA`, 415 | `Sec-CH-UA-Arch`, 416 | `Sec-CH-UA-Bitness`, 417 | `Sec-CH-UA-Full-Version`, 418 | `Sec-CH-UA-Full-Version-List`, 419 | `Sec-CH-UA-Mobile`, 420 | `Sec-CH-UA-Model`, 421 | `Sec-CH-UA-Platform`, 422 | `Sec-CH-UA-Platform-Version`, or 423 | `Sec-CH-UA-WoW64`. 424 | 425 | Note: A client hints token will also match the request header sent by the user agent when 426 | appropriate (as determined by the request processing algorithm). 427 | 428 | Policy-controlled features {#policy-controlled-features} 429 | ------------- 430 | 431 | This document defines policy-controlled client hints features, 432 | the following [=policy-controlled features=]: 433 | 434 | - ch-save-data which has a [=default allowlist=] of `'*'` 435 | - ch-dpr which has a [=default allowlist=] of `'self'` 436 | - ch-width which has a [=default allowlist=] of `'self'` 437 | - ch-viewport-width which has a [=default allowlist=] of `'self'` 438 | - ch-viewport-height which has a [=default allowlist=] of `'self'` 439 | - ch-device-memory which has a [=default allowlist=] of `'self'` 440 | - ch-rtt which has a [=default allowlist=] of `'self'` 441 | - ch-downlink which has a [=default allowlist=] of `'self'` 442 | - ch-ect which has a [=default allowlist=] of `'self'` 443 | - ch-prefers-color-scheme which has a [=default allowlist=] of `'self'` 444 | - ch-prefers-reduced-motion which has a [=default allowlist=] of `'self'` 445 | - ch-ua which has a [=default allowlist=] of `'*'` 446 | - ch-ua-arch which has a [=default allowlist=] of `'self'` 447 | - ch-ua-bitness which has a [=default allowlist=] of `'self'` 448 | - ch-ua-form-factors which has a [=default allowlist=] of `'self'` 449 | - ch-ua-full-version which has a [=default allowlist=] of `'self'` 450 | - ch-ua-full-version-list which has a [=default allowlist=] of `'self'` 451 | - ch-ua-mobile which has a [=default allowlist=] of `'*'` 452 | - ch-ua-model which has a [=default allowlist=] of `'self'` 453 | - ch-ua-platform which has a [=default allowlist=] of `'*'` 454 | - ch-ua-platform-version which has a [=default allowlist=] of `'self'` 455 | - ch-ua-wow64 which has a [=default allowlist=] of `'self'` 456 | 457 | Issue: Should we tie low-entropy-ness to allowlists, generally? 458 | 459 | Low-entropy hint table {#low-entropy-table} 460 | ------- 461 | The low-entropy hint table 462 | below defines hints that are safe to send by default due to their low amounts of entropy. 463 | 464 | A high-entropy client hint is a client hint that is not in the 465 | low-entropy hint table. 466 | 467 | 468 | 469 | 470 | Name 471 | Value 472 | 473 | 474 | `Save-Data` 475 | a suitable Save-Data value 476 | 477 | `Sec-CH-UA` 478 | a suitable UA value 479 | 480 | `Sec-CH-UA-Mobile` 481 | a suitable Mobile value 482 | 483 | `Sec-CH-UA-Platform` 484 | a suitable Platform value 485 | 486 | 487 | Note: If the value transmitted by `Save-Data` is the empty string, the header will be omitted entirely. 488 | This is done to reduce redundant header information sent by default. 489 | 490 | Find client hint value {#find-client-hint-value-section} 491 | ------------ 492 | 493 | When asked to find client hint value, given |hint| as input, switch on |hint| and return the result: 494 | 495 | `Save-Data` 496 | a suitable Save-Data value 497 | `DPR` 498 | a suitable DPR value 499 | `Viewport-Width` 500 | a suitable Viewport-Width value 501 | `Viewport-Height` 502 | a suitable Viewport-Height value 503 | `Width` 504 | a suitable Width value 505 | `Device-Memory` 506 | a suitable Device-Memory value 507 | `RTT` 508 | a suitable RTT value 509 | `Downlink` 510 | a suitable Downlink value 511 | `ECT` 512 | a suitable ECT value 513 | `Prefers-Color-Scheme` 514 | a suitable color theme value 515 | `Prefers-Reduced-Motion` 516 | a suitable Reduced-Motion value 517 | `UA` 518 | a suitable UA value 519 | `UA-Arch` 520 | a suitable Arch value 521 | `UA-Bitness` 522 | a suitable Bitness value 523 | `UA-Full-Version` 524 | a suitable Full-Version value 525 | `UA-Full-Version-List` 526 | a suitable Full-Version-List value 527 | `UA-Mobile` 528 | a suitable Mobile value 529 | `UA-Model` 530 | a suitable Model value 531 | `UA-Platform` 532 | a suitable Platform value 533 | `UA-Platform-Version` 534 | a suitable Platform-Version value 535 | `UA-WoW64` 536 | a suitable WoW64 value 537 | 538 | 539 | Issue: Links for image features are broken, need to actually define that and link to them. 540 | 541 | Security and Privacy considerations {#privacy} 542 | =========== 543 | 544 | This specification exposes information regarding the user's preferences and agent, which can be used as an active fingerprinting vector. 545 | [=User agents=] implementing this specification need to be aware of that, and take that into consideration when deciding whether to implement specific hints, 546 | modify their returned values for a given hint, or omit the hint entirely. 547 | 548 | For example, the user might have a site specific setting to override or disable specific client hints to reduce the potential for fingerprinting. 549 | 550 | Terms {#terms} 551 | ==== 552 | 553 | The following terms are defined in the HTTP specifications: 554 | field-name 555 | -------------------------------------------------------------------------------- /reliability.md: -------------------------------------------------------------------------------- 1 | # Client Hint Reliability 2 | 3 | ## Authors 4 | 5 | * David Benjamin 6 | * Aaron Tagliaboschi 7 | 8 | ## Introduction 9 | 10 | [HTTP Client Hints](https://www.rfc-editor.org/rfc/rfc8942.html) can replace passive fingerprinting surfaces with server-requested (and [potentially deniable](https://github.com/bslassey/privacy-budget)) client headers. However, the client may have out-of-date information on the server preferences when it sends a request. On the first page load, the client may not know to send any hints at all. This document describes a pair of mechanisms to fix this: 11 | 12 | 1. an HTTP-header-based retry to ensure critical Client Hints are reliably available 13 | 1. a connection-level optimization to avoid the performance hit of a retry in most cases 14 | 15 | For the draft specifications, see: 16 | 17 | * [draft-davidben-http-client-hint-reliability](https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability) 18 | * [draft-vvv-httpbis-alps](https://tools.ietf.org/html/draft-vvv-httpbis-alps) 19 | * [draft-vvv-tls-alps](https://tools.ietf.org/html/draft-vvv-tls-alps) 20 | 21 | 22 | ### Goals 23 | 24 | The design should: 25 | 26 | * Ensure requests use up-to-date server preferences 27 | * Avoid an extra network round-trip in the common case 28 | * Be robust to a client declining to send a Client Hint (user preferences, etc.) 29 | * Require minimal server complexity 30 | 31 | 32 | ### Non-Goals 33 | 34 | This design does _not_ force the client to send a Client Hint. It still may not support the hint or choose not to send it. This design also only aims to avoid a round-trip cost _most of the time_. Round-trips are sometimes unavoidable. 35 | 36 | 37 | ## Critical-CH 38 | 39 | Some Client Hints are optimizations, while others meaningfully change the page. For example, a site may use `Device-Memory` to serve simple and complex variants, and `Viewport-Width` for a server-side rendering optimization. If only the first request lacks `Device-Memory`, the site will jarringly switch versions between page loads. The server could try to detect this and self-redirect, but this will loop if the client declined to send the hint, or simply didn’t implement it. 40 | 41 | We move retry to the client with a new response header, [`Critical-CH`](https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability#section-3), with a list of _critical_ hints. If, after processing the `Accept-CH` header, the client would have sent a critical hint, it retries the request. Otherwise, it uses the response as-is. E.g, the initial request may be: 42 | 43 | ``` 44 | GET / HTTP/1.1 45 | Host: example.com 46 | 47 | HTTP/1.1 200 OK 48 | Content-Type: text/html 49 | Accept-CH: Device-Memory, DPR, Viewport-Width 50 | Vary: Device-Memory, Viewport-Width 51 | Critical-CH: Device-Memory 52 | (Body has default complex version of page) 53 | ``` 54 | 55 | 56 | The client records the `Accept-CH` preferences. It would have sent each of these hints and `Device-Memory` is critical, so it retries the request and receives the simpler version of the page. 57 | 58 | ``` 59 | GET / HTTP/1.1 60 | Host: example.com 61 | Device-Memory: 0.5 62 | DPR: 2 63 | Viewport-Width: 320 64 | 65 | HTTP/1.1 200 OK 66 | Content-Type: text/html 67 | Accept-CH: Device-Memory, DPR, Viewport-Width 68 | Vary: Device-Memory, Viewport-Width 69 | Critical-CH: Device-Memory 70 | (Body has simpler version of page) 71 | ``` 72 | 73 | 74 | ## Connection-level settings 75 | 76 | Fundamentally, any HTTP request using server information needs a round-trip to get that information. However, we can reuse the TLS handshake round-trip and send client hint preferences in the same flight as the TLS ServerHello, when TLS 1.3 starts encryption. This avoids a round-trip most of the time, but there are edge cases where a round-trip is unavoidable. 77 | 78 | Here we describe one possible encoding. See below for other options. Note that web developers would not be directly interacting with these mechanisms. They would be implemented by server software, with the web developer configuring it somewhere. 79 | 80 | 81 | ### ACCEPT\_CH 82 | 83 | In HTTP/2 and HTTP/3, the server can send auxiliary frames such as [SETTINGS](https://httpwg.org/specs/rfc7540.html#SETTINGS) with parameters for the connection. We define an [`ACCEPT_CH`](https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability#section-4) frame with a list of (origin, accept-ch) tuples. When the client sends an HTTP request, if the client has received an `ACCEPT_CH` frame and the origin matches an entry in the list, it uses the matching server preferences. (See also [connection vs cache ordering](#connection-vs-cache-ordering).) 84 | 85 | 86 | ### Application-Layer Protocol Settings 87 | 88 | While it is [possible](#accept_ch-in-half-rtt-data), in some modes, to send HTTP/2 frames with the ServerHello, this is not required or reliable. HTTP/2 and HTTP/3 clients do not wait for these frames before sending requests. We fix this by introducing an [Application-Layer Protocol Settings (ALPS)](https://tools.ietf.org/html/draft-vvv-tls-alps) extension for TLS 1.3 which lifts protocol-specific server settings into the EncryptedExtensions message. In [HTTP/2 and HTTP/3](https://tools.ietf.org/html/draft-vvv-httpbis-alps), we use them to carry the `ACCEPT_CH` frame and others. 89 | 90 | 91 | ### Example 92 | 93 | A client that has never connected to a server before will pick up the Client Hint request with no additional round-trip cost: 94 | 95 | ``` 96 | ClientHello 97 | + alps 98 | ServerHello 99 | EncryptedExtensions 100 | + alps=(https://example.com, Device-Memory) 101 | ... 102 | Finished 103 | Finished 104 | GET / HTTP/2.0 105 | Host: example.com 106 | Device-Memory: 0.5 107 | HTTP/2.0 200 OK 108 | Vary: Device-Memory 109 | Accept-CH: Device-Memory 110 | Critical-CH: Device-Memory 111 | ``` 112 | 113 | Note that, although the server sends `Critical-CH`, the client will not retry because it already sent `Device-Memory`. 114 | 115 | ## Key scenarios 116 | 117 | ### First load with updated server 118 | 119 | Sites running server software with `ACCEPT_CH` and ALPS support, Client Hints would be available in the first request as above. 120 | 121 | ### First load without updated server 122 | 123 | Sites running older software can continue to use `Critical-CH` for Client Hint reliability, at a round-trip cost on the first page load. Once the server is updated to support the connection-level mechanisms, this round-trip cost will go away. 124 | 125 | ### Unsupported or declined hint 126 | 127 | Suppose, in the above example, the client will not send `Device-Memory`. It may not support it, or decline it for privacy reasons. Although the `ACCEPT_CH` frame requests it, the client does not send it: 128 | 129 | ``` 130 | GET / HTTP/2.0 131 | Host: example.com 132 | ``` 133 | 134 | The server responds as best it can without the hint and sends header-level preferences. 135 | 136 | ``` 137 | HTTP/2.0 200 OK 138 | Vary: Device-Memory 139 | Accept-CH: Device-Memory 140 | Critical-CH: Device-Memory 141 | ``` 142 | 143 | The client evaluates the new `Accept-CH` header, determines it would not do anything different, and uses the response as-is. The user gets a consistent experience without accidental infinite redirect loops or extra round-trip costs. 144 | 145 | 146 | ### Non-critical hints 147 | 148 | Some Client Hints may not be worth a round-trip. For instance, a page may use the `Viewport-Width` hint for some server-side rendering optimization. If the hint is missing, the result still renders correctly. On the first visit, the `ACCEPT_CH` frame will still usually provide the hint anyway. If, however, the page load hits an edge case where this does not work, the HTTP request is: 149 | 150 | ``` 151 | GET / HTTP/1.1 152 | Host: example.com 153 | 154 | HTTP/1.1 200 OK 155 | Content-Type: text/html 156 | Vary: Viewport-Width 157 | Accept-CH: Viewport-Width 158 | ``` 159 | 160 | Although the page requests `Viewport-Width`, it is not critical, so the browser uses the response as-is. It remembers the `Viewport-Width` preference, so later page loads send the hint. 161 | 162 | 163 | ### Site changes 164 | 165 | A site’s HTTP frontend and content are often separated. It may use a CDN or the site may just be a collection of files on the filesystem. This means the site’s `Accept-CH` preferences may be updated without dropping existing HTTP connections. 166 | 167 | A client with an open HTTP connection would have both its `Accept-CH` cache and the connection-level `ACCEPT_CH` frame out-of-date. Without other information, it will send Client Hints based on the old preferences. Here, the `Critical-CH` mechanism restores reliability. This is an example where the connection-level optimization is not sufficient. 168 | 169 | A client without an open HTTP connection would have outdated `Accept-CH` cache but see an up-to-date `ACCEPT_CH` frame when it connects for the next request. Depending on the order between the two (see [discussion](#connection-vs-cache-ordering)), this may avoid the round-trip or lean on `Critical-CH`. 170 | 171 | 172 | ## Detailed design discussion 173 | 174 | 175 | ### Why two mechanisms? 176 | 177 | `Critical-CH` costs a round-trip, so making `ACCEPT_CH` + ALPS always work would seem preferable. However, this is not always possible: 178 | 179 | * The site may be running older software and have difficulty adopting `ACCEPT_CH` + ALPS. 180 | * If the [site changes](#site-changes) while connections are open, the connection-level settings will also be out-of-date. 181 | * Multiple origins may share connections with [HTTP/2 cross-name pooling](https://httpwg.org/specs/rfc7540.html#reuse). Some origins may not be in the `ACCEPT_CH` frame, particularly if the server uses wildcard subdomains. (Note the browser may [partition connection pools](https://docs.google.com/document/d/1V8sFDCEYTXZmwKa_qWUfTVNAuBcPsu6FC0PhqMD6KKQ/edit), which would limit these scenarios.) 182 | 183 | Thus we provide `Critical-CH` as a simple baseline mechanism, with connection-level settings as an added optimization. 184 | 185 | 186 | ### TLS 1.3 0-RTT 187 | 188 | TLS 1.3 includes a 0-RTT optimization which allows the client to send application data after the TLS ClientHello without waiting for the server. This saves a round-trip, but the client will not have received a `ACCEPT_CH` frame yet. 189 | 190 | 0-RTT is only possible after the initial connection to the server, so, in most cases, the client will already have up-to-date Accept-CH preferences cached. Neither `Critical-CH` nor the `ACCEPT_CH` frame is necessary. 191 | 192 | In some edge cases, the cache may be out-of-date. The server may since have changed, or as a consequence of some cross-name pooling behaviors. The `Critical-CH` header again restores reliability, at the cost of a retry. (Note: ALPS itself must interact with 0-RTT cleanly. It is likely that the server would decline 0-RTT when the saved settings are stale.) 193 | 194 | 195 | ### Retry limits 196 | 197 | To avoid infinite loops, the client should not retry more than once per request. Additionally, it should only retry GET requests. 198 | 199 | 200 | ### Connection vs cache ordering 201 | 202 | With two sources of Accept-CH information, we must decide what order to resolve them in. If the connection information always overrides the header cache, a client with a long-lived connection from before the site made a change will not pick up new values. This would pay round-trips repeatedly. If the header cache overrides connection information, we avoid this but may unnecessarily pay a round-trip once if the site changed while there wasn’t a connection open (see “Site changes” above). We could also pick more complex options like unioning them or tracking which was received more recently. 203 | 204 | 205 | ## Considered alternatives 206 | 207 | 208 | ### Alternate connection-level mechanisms 209 | 210 | The proposal above uses an `ACCEPT_CH` HTTP frame and a TLS extension (ALPS) to deliver it reliably. Here we discuss alternate wire formats. 211 | 212 | 213 | #### Client-hint-specific TLS extension 214 | 215 | We could simply define an `http_accept_client_hints` TLS extension. This would additionally work for HTTP/1.1. However, this pattern adds more TLS API surface every time we need connection-level metadata. Some site administrators rarely update libraries, so adding one general-purpose extension for HTTP parameters seems preferable. 216 | 217 | The loss of HTTP/1.1 coverage seems less important. Any connection-level change would require a server software upgrade. HTTP/2 is five years old now and a substantial performance win. Sites concerned with performance should deploy it anyway. 218 | 219 | 220 | #### SETTINGS and EXTENDED\_SETTINGS 221 | 222 | An earlier iteration of this design used an HTTP/2 and HTTP/3 SETTINGS value rather than a frame. However, SETTINGS values can only be integers, so this would not work. There was an [EXTENDED\_SETTINGS](https://tools.ietf.org/id/draft-bishop-httpbis-extended-settings-01.html) proposal which allows variable-width settings values, which would work as an alternative to a dedicated frame. (See [related discussion](https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0127.html).) 223 | 224 | 225 | #### ACCEPT\_CH in half-RTT data 226 | 227 | We could add `ACCEPT_CH` without ALPS. However, clients cannot reliably wait for it without a round-trip penalty: 228 | 229 | * In TLS 1.2 with False Start, waiting for server data adds a round-trip delay (negating the benefit of False Start). 230 | * In TLS 1.3, the server can send frames in half-RTT data, but there is no guarantee it will do so. There is also no way for the client to tell if the server does this, or how many frames to wait for. Any HTTP/2 client that waits for `ACCEPT_CH` thus risks paying a round-trip delay. 231 | 232 | The client could opportunistically read `ACCEPT_CH` from half-RTT data, but without a delimiter, this is unreliable even with servers that use half-RTT data. If it is reliable enough in practice, the gaps could be filled `Critical-CH`. However, many servers do not support half-RTT in 1-RTT connections, and this seems needlessly flaky. A more robust solution for HTTP parameter negotiation seems worthwhile. 233 | 234 | 235 | #### Half-RTT data indicator 236 | 237 | Finally, we could use half-RTT data, but introduce a TLS extension for the server to indicate the end of half-RTT data with some post-handshake message. The client can then reliably wait for it without risking a round-trip delay. 238 | 239 | This could work, but it seems needlessly complex, particularly when integrated with HTTP/3. (TLS post-handshake messages in QUIC are not ordered relative to application data.) Streaming half-RTT data on the server also has some [API challenges](https://mailarchive.ietf.org/arch/msg/tls/hymweZ66b2C8nnYyXF8cwj7qopc/). Finally, while this option does not modify HTTP/2’s wire image, it modifies the I/O patterns. This still means a change in HTTP/2 implementations and the protocol itself. 240 | 241 | #### DNS 242 | 243 | We could try to get the signal even earlier, such as through the [HTTPS DNS record](https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-02). This has security and operational issues. DNS records are largely not authenticated by the origin today, so this would allow the resolver to tamper with the web page. As this is an out-of-band signal, there are also operational difficulties for servers making sure the DNS information and server preferences are in sync. Today, web developers do not need to carefully synchronize their DNS records with web content. Finally, it is likely that coverage will be incomplete. An [old experiment](https://www.imperialviolet.org/2015/01/17/notdane.html) suggested, at the time, 4–5% of users could not even fetch TXT records. 244 | 245 | An in-band signal in the connection avoids these concerns while still delivering the data before the first HTTP request. 246 | 247 | 248 | ### Alternate retry mechanisms 249 | 250 | 251 | #### Server-triggered retry 252 | 253 | Rather than a client-triggered retry, the server could perform the retry instead. For instance, the server could return a self-redirect if a critical client hint was missing. This has two problems: 254 | 255 | First, a missing Client Hint does not immediately imply a retry. The client may not support the Client Hint, or it may have intentionally omitted it due to user preferences, [Privacy Budget](https://github.com/bslassey/privacy-budget), or other client policy. The client could expose richer information to implement this (e.g. include the list of _all_ supported Client Hints in each request), but this wastes bandwidth and results in even more complex server logic. 256 | 257 | Second, we wish to minimize developer obligations here. A server-triggered retry may be complex and easily trigger an infinite loop if wrong. Moreover, this code is not exercised after the first page load, so routine testing would not reveal mistakes. The `Critical-CH` header is the minimal additional overhead over the already required `Vary` header. 258 | 259 | 260 | #### Reuse Accept-CH or Vary instead of a new header 261 | 262 | The server is already required to send `Accept-CH` and `Vary` headers with lists of Client Hints, so we could reuse those. However, this would result in more retries than necessary. `Accept-CH` may contain Client Hints used by other resources that this one ignores. `Vary` may contain Client Hints that this resource used, but only as an optimization. 263 | 264 | 265 | #### UA heuristics on Client Hint criticality 266 | 267 | The above alternative could be combined with built-in client assumptions that, e.g., the `Viewport-Width` Client Hint is never critical, while the User-Agent Client Hints always are. 268 | 269 | 270 | ## References & acknowledgements 271 | 272 | This design was based on discussions with Ilya Grigorik, Nick Harper, Victor Vasiliev, and Yoav Weiss. 273 | -------------------------------------------------------------------------------- /tag-security-privacy-third-party-delegation.md: -------------------------------------------------------------------------------- 1 | # TAG Security & Privacy Questionnaire Answers for *Markup based Client Hints delegation for third-party content* # 2 | 3 | * **Author:** arichiv@chromium.org 4 | * **Questionnaire Source:** https://www.w3.org/TR/security-privacy-questionnaire/#questions 5 | 6 | ## Questions ## 7 | 8 | **1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary?** 9 | 10 | This feature exposes all the same information exposed today via the User-Agent string. See the response to question 8 for more details. Developers typically use this information for differential content serving, or to work around bugs. See https://github.com/WICG/ua-client-hints#use-cases for more use cases in more detail. 11 | 12 | The key difference between the UA string and UA-CH is that it moves the model from passive to active. Rather than a site passively receiving all possible information for all requests, UA-CH requires the site to make active requests for hints it needs in such a way that a User Agent may observe such calls and intervene, depending on UA privacy policies or user preferences. 13 | 14 | **2. Is this specification exposing the minimum amount of information necessary to power the feature?** 15 | 16 | We believe so, yes. 17 | 18 | **3. How does this specification deal with personal information or personally-identifiable information or information derived thereof?** 19 | 20 | It does not deal directly in PII, however information provided by the User-Agent string may be used for passive fingerprinting. The EFF estimates 10 bits of entropy can be obtained from the UA string. UA-CH provides a path forward to reduce the default passive entropy sent for all requests. By moving this information to an active surface, UAs could monitor and apply privacy interventions based on principled UA policies such as Safari’s [Intelligent Tracking Prevention](https://webkit.org/tracking-prevention/), Firefox’s [Enhanced Tracking Protection](https://blog.mozilla.org/en/products/firefox/latest-firefox-rolls-out-enhanced-tracking-protection-2-0-blocking-redirect-trackers-by-default/), Chrome’s [Privacy Budget](https://github.com/bslassey/privacy-budget) proposal, or similar. 21 | 22 | **4. How does this specification deal with sensitive information?** 23 | 24 | If a user agent considers certain UA hints to be sensitive (for example, bitness, device model, or CPU architecture), this specification encourages them to return the empty string or a fictitious value (see the end of https://wicg.github.io/ua-client-hints/#http-ua-hints). UAs are free to identify which hints might be sensitive, and in which contexts, according to their privacy policies (ITP, ETP, Privacy Budget, etc.). 25 | 26 | **5. Does this specification introduce new state for an origin that persists across browsing sessions?** 27 | 28 | This specification does in the sense that it provides additional hints that may be in the Accept-CH cache (provided by Client Hints Infrastructure): https://wicg.github.io/client-hints-infrastructure/#accept-ch-cache-definition 29 | 30 | **6. What information from the underlying platform, e.g. configuration data, is exposed by this specification to an origin?** 31 | 32 | In addition to information about a user agent, this specification may expose the brand name, version, architecture, bitness, and “mobileness” of the underlying operating system, as well as device model (for non-desktop platforms). The same info can be obtained directly (or inferred indirectly) from the UA string today, e.g., the string “(Windows NT 10.0; Win64; x64)” denotes a 64-bit browser running on Windows 10 (64-bit). With UA-CH, only the platform name and “mobileness” is exposed by default. To get the other information, an origin needs to explicitly request it. 33 | 34 | **7. Does this specification allow an origin access to sensors on a user’s device** 35 | 36 | No. 37 | 38 | **8. What data does this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts.** 39 | 40 | In addition to the data described in question 6, this specification may expose UA brand name, UA major version, and UA full version. All of this information is already exposed in the User-Agent header. 41 | 42 | The difference between UA-CH and the UA string, is that an origin needs to request this data -- with the exception of platform name, UA brand name, UA major version, and platform mobileness. It’s not sent by default for all requests (and subresource requests). The UA is free to grant, deny, or even to return the empty string or fake data for such requests, according to their privacy policies (ITP, ETP, Privacy Budget, etc.). 43 | 44 | **9. Does this specification enable new script execution/loading mechanisms?** 45 | 46 | No. 47 | 48 | **10. Does this specification allow an origin to access other devices?** 49 | 50 | No. 51 | 52 | **11. Does this specification allow an origin some measure of control over a user agent’s native UI?** 53 | 54 | No. 55 | 56 | **12. What temporary identifiers might this specification create or expose to the web?** 57 | 58 | Each new client hint in this specification can be abused to store 1 extra bit in the Accept-CH cache, as described at https://wicg.github.io/client-hints-infrastructure/#accept-ch-cache-definition. No other new identifying information is exposed. 59 | 60 | **13. How does this specification distinguish between behavior in first-party and third-party contexts?** 61 | 62 | This specification inherits the following characteristics from Client Hints Infrastructure, “Origin opt-in applies to same-origin assets only and delivery to third-party origins is subject to explicit first party delegation via Permissions Policy, enabling tight control over which third party origins can access requested hint data.” Hints need to be explicitly delegated by developers from a first- to third-party context. 63 | 64 | **14. How does this specification work in the context of a user agent’s Private Browsing or "incognito" mode?** 65 | 66 | It will work the same. Accept-CH preferences will not be maintained between “private” and “non-private” browsing sessions. See https://wicg.github.io/client-hints-infrastructure/#accept-ch-cache-definition 67 | 68 | **15. Does this specification have a "Security Considerations" and "Privacy Considerations" section?** 69 | 70 | Yes. https://wicg.github.io/ua-client-hints/#security-privacy 71 | 72 | **16. Does this specification allow downgrading default security characteristics?** 73 | 74 | No. 75 | 76 | **1. What information might this feature expose to Web sites or other parties, and for what purposes is that exposure necessary?** 77 | 78 | This feature allows origins to delegate client hints to third parties via HTML markup (a meta tag), something only currently possible via HTTP headers. This is being added to better support adaptable third party content (e.g., [variable fonts](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide), [color vector fonts](https://www.chromestatus.com/feature/5638148514119680), and [responsive images](https://github.com/w3c/webappsec-permissions-policy/issues/55#issuecomment-406627096)) used in contexts which permit modification of markup but not HTTP headers. 79 | 80 | The only added risk with markup is the possibility that third parties could inject delegation requests into the first party document that the first party had not intended. To mitigate that, we require that the delegation is only respected before javascript is executed, and not after. With this limitation, no actor not previously able to delegate client hints (via HTTP) should now be able to do so (via HTML). 81 | 82 | **2. Do features in your specification expose the minimum amount of information necessary to enable their intended uses?** 83 | 84 | Yes, it exposes no information not already possible to expose within the client hints system. It simply allows for HTML markup instead of HTTP headers. 85 | 86 | **3. How do the features in your specification deal with personal information, personally-identifiable information (PII), or information derived from them?** 87 | 88 | It does not deal directly in PII, however information provided by client hints can reveal device or browser characteristics. User agents can send the empty string if they wish to withhold requested client hints. 89 | 90 | **4. How do the features in your specification deal with sensitive information?** 91 | 92 | It does not handle sensitive information. 93 | 94 | **5. Do the features in your specification introduce new state for an origin that persists across browsing sessions?** 95 | 96 | No, this specification does not write changes to the Accept-CH cache: https://wicg.github.io/client-hints-infrastructure/#accept-ch-cache-definition 97 | 98 | **6. Do the features in your specification expose information about the underlying platform to origins?** 99 | 100 | Yes, but not by default. It makes it possible for a first party to intentionally delegate client hints to a third party. 101 | 102 | **7. Does this specification allow an origin to send data to the underlying platform?** 103 | 104 | Yes, the specification allows the origin to indicate which features (client hints) the origin wishes to receive and/or delegate to third party origins. 105 | 106 | **8. Do features in this specification enable access to device sensors?** 107 | 108 | No 109 | 110 | **9. What data do the features in this specification expose to an origin? Please also document what data is identical to data exposed by other features, in the same or different contexts.** 111 | 112 | See the answer to question 6. For a list of features see https://wicg.github.io/client-hints-infrastructure/#policy-controlled-features. 113 | 114 | **10. Do features in this specification enable new script execution/loading mechanisms?** 115 | 116 | No 117 | 118 | **11. Do features in this specification allow an origin to access other devices?** 119 | 120 | No 121 | 122 | **12. Do features in this specification allow an origin some measure of control over a user agent’s native UI?** 123 | 124 | No 125 | 126 | **13. What temporary identifiers do the features in this specification create or expose to the web?** 127 | 128 | Nothing beyond what's currently capable with Client Hints. 129 | 130 | **14. How does this specification distinguish between behavior in first-party and third-party contexts?** 131 | 132 | This specification inherits the following characteristics from Client Hints Infrastructure, “Origin opt-in applies to same-origin assets only and delivery to third-party origins is subject to explicit first party delegation via Permissions Policy, enabling tight control over which third party origins can access requested hint data.” Hints need to be explicitly delegated by developers from a first- to third-party context. 133 | 134 | **15. How do the features in this specification work in the context of a browser’s Private Browsing or Incognito mode?** 135 | 136 | It will work the same. Accept-CH preferences will not be maintained between “private” and “non-private” browsing sessions. See https://wicg.github.io/client-hints-infrastructure/#accept-ch-cache-definition 137 | 138 | **16. Does this specification have both "Security Considerations" and "Privacy Considerations" sections?** 139 | 140 | Yes. https://wicg.github.io/client-hints-infrastructure/#privacy 141 | 142 | **17. Do features in your specification enable origins to downgrade default security protections?** 143 | 144 | No 145 | 146 | **18. How does your feature handle non-"fully active" documents?** 147 | 148 | N/A 149 | 150 | **19. What should this questionnaire have asked?** 151 | 152 | N/A 153 | 154 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [80485] 3 | , "contacts": ["yoavweiss"] 4 | , "repo-type": "cg-report" 5 | } 6 | --------------------------------------------------------------------------------
2 | Title: Client Hints Infrastructure 3 | Shortname: ClientHintsInfra 4 | Level: 1 5 | Status: CG-Draft 6 | Group: WICG 7 | URL: https://wicg.github.io/client-hints-infrastructure 8 | Editor: Yoav Weiss, Google, yoav@yoav.ws, https://blog.yoav.ws 9 | Abstract: Specification of the Client Hints infrastructure and its integration with Fetch and HTML 10 | Markup Shorthands: markdown yes 11 | Repository: WICG/client-hints-infrastructure 12 |
15 | spec:html; type:element; text:link 16 | spec:html; type:element; text:script 17 | spec:fetch; type:dfn; for:/; text:fetch 18 | spec:fetch; type:dfn; for:Request; text:request 19 | spec:fetch; type:dfn; text:client 20 | spec:ServiceWorker; type:dfn; for:/; text: 21 | spec:url; type:dfn; for:url; text:origin 22 | spec:html; type:element; text:style 23 | spec:infra; type:dfn; text:user agent 24 | spec:html; type:dfn; text:navigable 25 |
28 | spec: HTML; urlPrefix: https://html.spec.whatwg.org/multipage/ 29 | urlPrefix: browsing-the-web.html 30 | type: dfn;text: populating a session history entry; url: populating-a-session-history-entry 31 | urlPrefix: semantics.html 32 | type: dfn; text: standard metadata names; url: standard-metadata-names 33 | spec: STRUCTURED-FIELDS; urlPrefix: https://www.rfc-editor.org/rfc/rfc8941.html#name- 34 | type: dfn 35 | text: sf-lists; url: lists 36 | spec: clear-site-data; urlPrefix: https://w3c.github.io/webappsec-clear-site-data/# 37 | type: dfn 38 | text: Clear-Site-Data Header; url: header 39 |
42 | { 43 | "PERMISSIONS-POLICY": { 44 | "authors": [ 45 | "Ian Clelland" 46 | ], 47 | "href": "https://w3c.github.io/webappsec-permissions-policy/", 48 | "publisher": "W3C", 49 | "title": "Permissions Policy" 50 | }, 51 | "CLIENT-HINT-RELIABILITY": { 52 | "authors": [ 53 | "David Benjamin" 54 | ], 55 | "href": "https://datatracker.ietf.org/doc/html/draft-davidben-http-client-hint-reliability", 56 | "publisher": "W3C", 57 | "title": "Client Hint Reliability" 58 | } 59 | } 60 |
A client hints set is a 137 | set of [=client hints token=]s. 138 | 139 | `Accept-CH` cache {#accept-ch-cache-definition} 140 | ---------------- 141 | 142 | An Accept-CH cache is owned by the user agent and is an [=ordered map=], 143 | [=keyed=] on origin (an [=url/origin=]), 144 | with a value of client hints set (a [=/client hints set=]). 145 | 146 | The Accept-CH cache can effectively act as an alternative cookie store, 147 | since sites can use each of the hints as a bit set on the client, and that information will be 148 | communicated to them on every request. As such, a user agent MUST evict that 149 | cache whenever the user clears their cookies or when session cookies expire. 150 | A user agent also MUST clear the Accept-CH according to the rules of the 151 | [=Clear-Site-Data Header=]. 152 | 153 | A site can clear the browser's `Accept-CH` cache for its origin by sending an empty `Accept-CH` header in a response. This sets the origin's [=/client hints set=] to an empty set. 154 | 155 | There MAY be multiple `Accept-CH` headers per-response and sf-lists can be split across lines as long as each line contains at least one token. 156 | 157 | Note: As the cache can only be modified by the top-level frame, it is considered to be partitioned. 158 | 159 | When asked to update the client hints set from cache given a |settingsObject|: 160 | 161 |
Document
For each hintToken in the list of [=client hints token=]s: 375 |
If request's header list contains 377 | hintToken, then remove hintToken from |request|'s [=request/header list=]. 378 |
ch-save-data
ch-dpr
ch-width
ch-viewport-width
ch-viewport-height
ch-device-memory
ch-rtt
ch-downlink
ch-ect
ch-prefers-color-scheme
ch-prefers-reduced-motion
ch-ua
ch-ua-arch
ch-ua-bitness
ch-ua-form-factors
ch-ua-full-version
ch-ua-full-version-list
ch-ua-mobile
ch-ua-model
ch-ua-platform
ch-ua-platform-version
ch-ua-wow64