blob: a9e10bf839d4ddf21d84570339ea5c9888574d6f [file] [log] [blame] [view]
Ramin Halavati2e7ffe4f2017-11-13 11:19:351# Network Traffic Annotations
2
3[TOC]
4
5This document presents a practical guide to using network traffic annotations in
6Chrome.
7
8
9## Problem Statement
10
11To make Chrome’s network communication transparent, we would need to be able to
12provide the following answers:
13* What is the intent behind each network request?
14* What user data is sent in the request, and where does it go?
15
Ramin Halavati6c1526e2018-04-06 05:44:3816Besides these requirements, the following information helps users, admins, and
17help desk:
Ramin Halavati2e7ffe4f2017-11-13 11:19:3518* How can a network communication be stopped or controlled?
19* What are the traces of the communication on the client?
20
21It should be noted that the technical details of requests are not necessarily
22important to the users, but in order to provide the intended transparency, we
23need to show that we have covered all bases and there are no back doors.
24
25
26## The Solution
27
28We can provide up to date, in-line documentation on origin, intent, payload, and
29control mechanisms of each network communication. This is done by adding a
30`NetworkTrafficAnnotationTag` to all network communication functions.
31Please note that as the goal is to specify the intent behind each network
32request and its payload, this metadata does not need to be transmitted with the
33request during runtime and it is sufficient to have it in appropriate positions
34in the code. Having that as an argument of all network communication functions
35is a mechanism to enforce its existence and showing the users our intent to
36cover the whole repository.
37
38
39## Best Practices
40
41### Where to add annotation?
42All network requests are ultimately sending data through sockets or native API
43functions, but we should note that the concern is about the main intent of the
44communication and not the implementation details. Therefore we do not need to
45specify this data separately for each call to each function that is used in the
46process and it is sufficient that the most rational point of origin would be
47annotated and the annotation would be passed through the downstream steps.
48Best practices for choosing annotation code site include where:
49 1. The origin of user’s intent or internal requirement for the request is
50 stated.
51 2. The controls over stopping or limiting the request (Chrome settings or
52 policies) are enforced.
53 3. The data that is sent is specified.
54If there is a conflict between where is the best annotation point, please refer
55to the `Partial Annotations` section for an approach to split annotation.
56
57### Merged Requests
58There are cases where requests are received from multiple sources and merged
59into one connection, like when a socket merges several data frames and sends
60them together, or a device location is requested by different components, and
61just one network request is made to fetch it. In these cases, the merge point
62can ensure that all received requests are properly annotated and just pass one
Ramin Halavati6c1526e2018-04-06 05:44:3863of them to the downstream step. It can also pass a local annotation stating that
64it is a merged request on behalf of other requests of type X, which were ensured
65to all have annotations.
Ramin Halavati2e7ffe4f2017-11-13 11:19:3566This decision is driven from the fact that we do not need to transmit the
67annotation metadata in runtime and enforced annotation arguments are just to
68ensure that the request is annotated somewhere upstream.
69
70
71## Coverage
Ramin Halavati6c1526e2018-04-06 05:44:3872Network traffic annotations are currently enforced on all url requests and
73socket writes, except for the code which is not compiled on Windows or Linux.
74This effort may expand to ChromeOS in future and currently there is no plan to
75expand it to other platforms.
Ramin Halavati2e7ffe4f2017-11-13 11:19:3576
77
78## Network Traffic Annotation Tag
79
80`net::NetworkTrafficAnnotationTag` is the main definition for annotations. There
81are few variants of it that are specified in later sections. The goal is to have
82one object of this type or its variants as an argument of all functions that
83create a network request.
84
85### Content of Annotation Tag
Glenn Hartmanndb9723b32022-01-07 14:57:2586Each network traffic annotation should specify the following items, as defined
87in the `NetworkTrafficAnnotation` message of
88`chrome/browser/privacy/traffic_annotation.proto`:
Ramin Halavati2e7ffe4f2017-11-13 11:19:3589* `uniqueـid`: A globally unique identifier that must stay unchanged while the
90 network request carries the same semantic meaning. If the network request gets
91 a new meaning, this ID needs to be changed. The purpose of this ID is to give
92 humans a chance to reference NetworkTrafficAnnotations externally even when
93 those change a little bit (e.g. adding a new piece of data that is sent along
94 with a network request). IDs of one component should have a shared prefix so
95 that sorting all NetworkTrafficAnnotations by unique_id groups those that
96 belong to the same component together.
Glenn Hartmanndb9723b32022-01-07 14:57:2597* `source`: These set of fields specify the location of annotation in
Ramin Halavati2e7ffe4f2017-11-13 11:19:3598 the source code. These fields are automatically set and do not need
99 specification.
Glenn Hartmanndb9723b32022-01-07 14:57:25100* `semantics`: These set of fields specify meta information about the
Ramin Halavati2e7ffe4f2017-11-13 11:19:35101 network request’s content and reason.
102 * `sender`: What component triggers the request. The components should be
103 human readable and don’t need to reflect the components/ directory. Avoid
Ramin Halavati6c1526e2018-04-06 05:44:38104 abbreviations, and use a common value for all annotations in one component.
Ramin Halavati2e7ffe4f2017-11-13 11:19:35105 * `description`: Plaintext description of the network request in language
106 that is understandable by admins (ideally also users). Please avoid
107 acronyms and describe the feature and the feature's value proposition as
108 well.
109 * `trigger`: What user action triggered the network request. Use a textual
110 description. This should be a human readable string.
Xinghui Lu5b9477d2023-05-04 20:15:55111 * `user_data`: What nature of data is being sent, as enums.
112 Any personally identifiable (PII) data, provided by user or generated
113 by Google, should be pointed out. You can include multiple
114 values, and you may want to supplement this with the data field.
Sugandha Goyal0ccc7402022-10-21 13:35:55115 All available User data enums can be found [here](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/privacy/traffic_annotation.proto?q=UserDataType).
Xinghui Lu5b9477d2023-05-04 20:15:55116 * `data`: Textual description of data being sent, for things that aren't
117 covered by user_data enum values. You can also use this field if
Sugandha Goyal0ccc7402022-10-21 13:35:55118 more context needs to be provided to describe user_data.
Ramin Halavati2e7ffe4f2017-11-13 11:19:35119 * `destination`: Target of the network request. It can be either the website
120 that user visits and interacts with, a Google service, a request that does
121 not go to network and just fetches a local resource, or other endpoints
122 like a service hosting PAC scripts. The distinction between a Google owned
123 service and website can be difficult when the user navigates to google.com
124 or searches with the omnibar. Therefore follow the following guideline: If
125 the source code has hardcoded that the request goes to Google (e.g. for
126 ZeroSuggest), use `GOOGLE_OWNED_SERVICE`. If the request can go to other
127 domains and is perceived as a part of a website rather than a native
Nicolas Arciniega15745e22019-10-09 20:42:35128 browser feature, use `WEBSITE`. Use `LOCAL` if the request is processed
Xinghui Lu5b9477d2023-05-04 20:15:55129 locally and doesn't go to network. If the request goes to a third-party proxy
130 first and then is forwarded to a Google service, use `PROXIED_GOOGLE_OWNED_SERVICE`.
131 Otherwise use `OTHER`. If `OTHER` is used, please add plain text description in `destination_other` field.
Ramin Halavati2e7ffe4f2017-11-13 11:19:35132 * `destination_other`: Human readable description in case the destination
133 points to `OTHER`.
Xinghui Lu5b9477d2023-05-04 20:15:55134 * `internal`: Data that is meant to be visible internally, example point of contacts,
Sugandha Goyalfcdaf212022-11-22 15:07:40135 should be placed inside internal field. This field should not be used in any
Sugandha Goyal18152792022-10-19 22:01:43136 external reports.
Xinghui Lu5b9477d2023-05-04 20:15:55137 * `contacts`: A person's or team's email address who are point-of-contact
Chris Mullinscb7ba912023-07-24 20:48:14138 for questions, issues, or bugs related to this network request. An
139 OWNERS file may also be specified using the `owners` field.
Sugandha Goyal0ccc7402022-10-21 13:35:55140 * `last_reviewed`: Date when this annotation was last reviewed in YYYY-MM-DD format.
Glenn Hartmanndb9723b32022-01-07 14:57:25141* `policy`: These set of fields specify the controls that a user may have
Ramin Halavati2e7ffe4f2017-11-13 11:19:35142 on disabling or limiting the network request and its trace.
Ramin Halavati2e7ffe4f2017-11-13 11:19:35143 * `cookies_allowed`: Specifies if this request stores and uses cookies or
144 not. Use values `YES` or `NO`.
145 * `cookies_store`: If a request sends or stores cookies/channel IDs/... (i.e.
146 if `cookies_allowed` is true), we want to know which cookie store is being
147 used. The answer to this question can typically be derived from the
148 URLRequestContext that is being used. The three most common cases will be:
149 * If `cookies_allowed` is false, leave this field unset.
150 * If the profile's default URLRequestContext is being used (e.g. from
151 `Profile::GetRequestContext())`, this means that the user's normal
152 cookies sent. In this case, put `user` here.
153 * If the system URLRequestContext is being used (for example via
154 `io_thread()->system_url_request_context_getter())`, put `system` here.
155 * Otherwise, please explain (e.g. SafeBrowsing uses a separate cookie
156 store).
157 * `setting`: Human readable description of how to enable/disable a feature
158 that triggers this network request by a user (e.g. “Disable ‘Use a web
159 service to help resolve spelling errors.’ in settings under Advanced”).
160 Note that settings look different on different platforms, make sure your
161 description works everywhere!
162 * `chrome_policy`: Policy configuration that disables or limits this network
Aiden Chiavatti479d874a2023-01-25 23:25:35163 request. This would be a text serialized protobuf of any **non-device**
164 enterprise policy. See policy list or
Glenn Hartmanndb9723b32022-01-07 14:57:25165 `out/Debug/gen/components/policy/proto/chrome_settings.proto` for the full
166 list of policies.
Aiden Chiavatti479d874a2023-01-25 23:25:35167 * Note: Use `chrome_device_policy` instead for device policies.
168 * `chrome_device_policy`: Policy configuration that disables or limits this
169 network request. This would be a text serialized protobuf of any
170 **device** enterprise policy. See
171 `components/policy/proto/chrome_device_policy.proto` for the full list of
172 policies.
173 * Note: Use `chrome_policy` instead for non-device policies (e.g. user
174 policies).
Ramin Halavati2e7ffe4f2017-11-13 11:19:35175 * `policy_exception_justification`: If there is no policy to disable or limit
Ramin Halavatic7c0bb032018-01-30 16:44:48176 this request, a justification can be presented here.
Sugandha Goyal0ccc7402022-10-21 13:35:55177 * `deprecated_policies`: Policy names disabling or limiting this network request
178 which are currently deprecated. These should be a subset of the policies in the
Xinghui Lu5b9477d2023-05-04 20:15:55179 `chrome_policy` field. If a policy is removed from the `chrome_policy` field,
Sugandha Goyal0ccc7402022-10-21 13:35:55180 then it should be removed from this field also.
Ramin Halavati2e7ffe4f2017-11-13 11:19:35181* `comments`: If required, any human readable extra comments.
182
183### Format and Examples
184Traffic annotations are kept in code as serialized protobuf. To define a
185`NetworkTrafficAnnotationTag`, you may use the function
186`net::DefineNetworkTrafficAnnotation`, with two arguments, the unique id, and
187all other fields bundled together as a serialized protobuf string.
188
189#### Good examples
190```cpp
191 net::NetworkTrafficAnnotationTag traffic_annotation =
192 net::DefineNetworkTrafficAnnotation("spellcheck_lookup", R"(
193 semantics {
194 sender: "Online Spellcheck"
195 description:
196 "Chrome can provide smarter spell-checking by sending text you "
197 "type into the browser to Google's servers, allowing you to use "
198 "the same spell-checking technology used by Google products, such "
199 "as Docs. If the feature is enabled, Chrome will send the entire "
200 "contents of text fields as you type in them to Google along with "
201 "the browser’s default language. Google returns a list of "
202 "suggested spellings, which will be displayed in the context menu."
203 trigger: "User types text into a text field or asks to correct a "
204 "misspelled word."
Nicolas Ouellet-Payeur7a9724ae2023-02-09 16:03:27205 internal {
206 contacts {
207 email: "chrome-spellcheck@google.com"
208 }
209 }
Sugandha Goyal0ccc7402022-10-21 13:35:55210 user_data {
211 type: USER_CONTENT
212 }
Ramin Halavati2e7ffe4f2017-11-13 11:19:35213 data: "Text a user has typed into a text field. No user identifier "
214 "is sent along with the text."
215 destination: GOOGLE_OWNED_SERVICE
Sugandha Goyal0ccc7402022-10-21 13:35:55216 last_reviewed: "2022-10-17"
Ramin Halavati2e7ffe4f2017-11-13 11:19:35217 }
218 policy {
219 cookies_allowed: NO
220 setting:
221 "You can enable or disable this feature via 'Use a web service to "
222 "help resolve spelling errors.' in Chrome's settings under "
223 "Advanced. The feature is disabled by default."
224 chrome_policy {
225 SpellCheckServiceEnabled {
226 SpellCheckServiceEnabled: false
227 }
228 }
229 })");
230```
231
232```cpp
233 net::NetworkTrafficAnnotationTag traffic_annotation2 =
234 net::DefineNetworkTrafficAnnotation(
235 "safe_browsing_chunk_backup_request",
236 R"(
237 semantics {
238 sender: "Safe Browsing"
239 description:
240 "Safe Browsing updates its local database of bad sites every 30 "
241 "minutes or so. It aims to keep all users up-to-date with the same "
242 "set of hash-prefixes of bad URLs."
243 trigger:
244 "On a timer, approximately every 30 minutes."
245 data:
246 "The state of the local DB is sent so the server can send just the "
247 "changes. This doesn't include any user data."
248 destination: GOOGLE_OWNED_SERVICE
Sugandha Goyalfcdaf212022-11-22 15:07:40249 internal {
250 contacts {
251 email: "chrome-safebrowsing@google.com"
252 }
253 }
Nicolas Ouellet-Payeur7a9724ae2023-02-09 16:03:27254 user_data {
255 type: NONE
256 }
257 last_reviewed: "2023-01-01"
Ramin Halavati2e7ffe4f2017-11-13 11:19:35258 }
259 policy {
260 cookies_allowed: YES
261 cookies_store: "Safe Browsing cookie store"
262 setting:
263 "Users can disable Safe Browsing by unchecking 'Protect you and "
264 "your device from dangerous sites' in Chromium settings under "
265 "Privacy. The feature is enabled by default."
266 chrome_policy {
267 SafeBrowsingEnabled {
268 policy_options {mode: MANDATORY}
269 SafeBrowsingEnabled: false
270 }
271 }
272 })");
273```
274
275#### Bad Examples
276```cpp
277 net::NetworkTrafficAnnotationTag bad_traffic_annotation =
278 net::DefineNetworkTrafficAnnotation(
279 ...
280 trigger: "Chrome sends this when [obscure event that is not related to "
281 "anything user-perceivable]."
282 // Please specify the exact user action that results in this request.
283 data: "This sends everything the feature needs to know."
284 // Please be precise, name the data items. If they are too many, name
285 // the sensitive user data and general classes of other data and refer
286 // to a document specifying the details.
287 ...
288 policy_exception_justification: "None."
289 // Check again! Most features can be disabled or limited by a policy.
290 ...
291 })");
292```
293
294#### Empty Template
295You can copy/paste the following template to define an annotation.
296```cpp
297 net::NetworkTrafficAnnotationTag traffic_annotation =
298 net::DefineNetworkTrafficAnnotation("...", R"(
299 semantics {
300 sender: "..."
301 description: "..."
302 trigger: "..."
303 data: "..."
304 destination: WEBSITE/GOOGLE_OWNED_SERVICE/OTHER
305 }
306 policy {
Ramin Halavati2e7ffe4f2017-11-13 11:19:35307 cookies_allowed: NO/YES
308 cookies_store: "..."
309 setting: "..."
310 chrome_policy {
311 [POLICY_NAME] {
312 [POLICY_NAME]: ...
313 }
314 }
315 policy_exception_justification = "..."
316 }
317 comments: "..."
318 )");
319```
320
321
322## Testing for errors
323
324There are several checks that should be done on annotations before submitting a
325change list. These checks include:
326* The annotations are syntactically correct.
327* They have all required fields.
328* Partial annotations and completing parts match (please refer to the next
329 section).
330* Annotations are not incorrectly defined.
331 * e.g., traffic_annotation = NetworkTrafficAnnotation({1}).
332* All usages from Chrome have annotation.
Bella Bahaf76f4a2020-08-03 22:22:56333* That the annotation appears in
334 `tools/traffic_annotation/summary/grouping.xml`. When adding a new annotation,
335 it must also be included in `grouping.xml` for reporting purposes (please
336 refer to the **Annotations Review**).
Bella Bah2b772c132020-08-05 17:01:37337
Ramin Halavati2e7ffe4f2017-11-13 11:19:35338
Ramin Halavati6c1526e2018-04-06 05:44:38339### Presubmit tests
Nicolas Ouellet-Payeur35662942021-08-03 16:01:37340To perform tests prior to submit, one can use the `auditor.py`
341script. It runs over the whole repository, extracts
342all the annotations from C++ code, and then checks them for correctness.
Ehsan Kia735f6b42020-02-27 18:14:59343
Nicolas Ouellet-Payeur35662942021-08-03 16:01:37344Running the `auditor.py` script requires a build directory in which you just
345built the `chrome` target. You can invoke it like this:
346`vpython3 tools/traffic_annotation/scripts/auditor/auditor.py
347 --build-path=out/Default`
Ramin Halavati6c1526e2018-04-06 05:44:38348
349### Waterfall tests
350Two commit queue trybots test traffic annotations on changed files using the
351scripts in `tools/traffic_annotation/scripts`. To run these tests faster and to
Nicolas Arciniega15745e22019-10-09 20:42:35352avoid spamming the commit queue if an unforeseen error has happened in
353downstream scripts or tools, they are run in error resilient mode, only on
354changed files, and using heuristics to decide which files to process.
Ramin Halavati6c1526e2018-04-06 05:44:38355An FYI bot runs more detailed tests on the whole repository and with different
356switches, to make sure that the heuristics that trybot tests use and the limited
357scope of tests have not neglected any issues.
Ramin Halavati2e7ffe4f2017-11-13 11:19:35358
359
360## Annotations Review
361
Ramin Halavati6c1526e2018-04-06 05:44:38362Network traffic annotations require review before landing in code and this is
363enforced through keeping a summary of annotations in
Bella Bahaf76f4a2020-08-03 22:22:56364`tools/traffic_annotation/summary/annotations.xml`. Once a new annotation is added,
365one is updated, or deleted, this file should also be updated. To update the
Nicolas Ouellet-Payeur35662942021-08-03 16:01:37366`annotations.xml` file automatically, one can run `auditor.py`
Bella Bahaf76f4a2020-08-03 22:22:56367as specified in presubmit tests. But if it is not possible to do so (e.g., if
368you are changing the code from an unsupported platform or you don’t have a
369compiled build directory), the code can be submitted to the trybot and the test
Bella Bah2b772c132020-08-05 17:01:37370on trybot will tell you the required modifications.
Ramin Halavati2e7ffe4f2017-11-13 11:19:35371
Bella Bahaf76f4a2020-08-03 22:22:56372In order to help make external reports easier, annotation unique ids should be
373mentioned in `tools/traffic_annotation/summary/grouping.xml`. Once a new
374annotation is added, or a preexisting annotation's unique id changes, this file
375should also be updated. When adding a new annotation, make sure it is placed
376within an appropriate group of `grouping.xml`. In the rare case that none of
377the groups are appropriate, one can create a new group for the annotation; the
378arrangement of annotations and group names in `grouping.xml` may be later
379updated by a technical writer to better coincide with the external reports.
Ramin Halavati2e7ffe4f2017-11-13 11:19:35380
381## Partial Annotations (Advanced)
382
383There are cases where the network traffic annotation cannot be fully specified
384in one place. For example, in one place we know the trigger of a network request
385and in another place we know the data that will be sent. In these cases, we
386prefer that both parts of the annotation appear in context so that they are
387updated if code changes. Partial annotations help splitting the network traffic
388annotation into two pieces. In these cases, we call the first part, the partial
389annotation, and the part the completes it, the completing annotation. Partial
390annotations and completing annotations do not need to have all annotation
391fields, but their composition should have all required fields.
392
393### Defining a Partial Annotation
394To define a partial annotation, one can use
395`net::DefinePartialNetworkTrafficAnnotation` function. Besides the unique id and
396annotation text, this function requires the unique id of the completing part.
397For example, a partial annotation that only specifies the semantics part or a
398request with unique id "omnibox_prefetch_image", and is completed later using an
399annotation with unique id "bitmap_fetcher", can be defined as follows:
400
401```cpp
402 net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
403 net::DefinePartialNetworkTrafficAnnotation("omnibox_prefetch_image",
404 "bitmap_fetcher", R"(
405 semantics {
406 sender: "Omnibox"
407 Description: "..."
408 Trigger: "..."
409 Data: "..."
410 destination: WEBSITE
411 })");
412```
413
414### Nx1 Partial Annotations
415The cases where several partial annotations may be completed by one completing
416annotation are called Nx1. This also matches where N=1. To define a completing
417annotation for such cases, one can use net::CompleteNetworkTrafficAnnotation
418function. This function receives a unique id, the annotation text, and a
419`net::PartialNetworkTrafficAnnotationTag` object. Here is an example of a
420completing part for the previous example:
421
422```cpp
423 net::NetworkTrafficAnnotationTag traffic_annotation =
424 net::CompleteNetworkTrafficAnnotation("bitmap_fetcher",
425 partial_traffic_annotation, R"(
426 policy {
427 cookies_allowed: YES
428 cookies_store: "user"
429 setting: "..."
430 chrome_policy {...}
431 })");
432```
433
434### 1xN Partial Annotations
435There are cases where one partial traffic annotation may be completed by
436different completing annotations. In these cases,
437`net::BranchedCompleteNetworkTrafficAnnotation` function can be used. This
438function has an extra argument that is common between all branches and is
439referred to by the partial annotation. For the above examples, if there would be
440two different ways of completing the received partial annotation, the following
441the definition can be used:
442
443```cpp
444if (...) {
445 return net::BranchedCompleteNetworkTrafficAnnotation(
446 "bitmap_fetcher_type1", "bitmap_fetcher",
447 partial_traffic_annotation, R"(
448 policy {
449 cookies_allowed: YES
450 cookies_store: "user"
451 setting: "..."
452 chrome_policy {...}
453 })");
454 } else {
455 return net::BranchedCompleteNetworkTrafficAnnotation(
456 "bitmap_fetcher_type2", "bitmap_fetcher",
457 partial_traffic_annotation, R"(
458 policy {
459 cookies_allowed: YES
460 cookies_store: "system"
461 setting: "..."
462 chrome_policy {...}
463 })");
464```
465
466Please refer to `tools/traffic_annotation/sample_traffic_annotation.cc` for more
467detailed examples.
468
469
470## Mutable Annotations (Advanced)
471
472`net::NetworkTrafficAnnotationTag` and `net::PartialNetworkTrafficAnnotationTag`
473are defined with constant internal argument(s), so that once they are created,
474they cannot be modified. There are very few exceptions that may require
475modification of the annotation value, like the ones used by mojo interfaces
476where after serialization, the annotation object is first created, then receives
477value. In these cases, `net::MutableNetworkTrafficAnnotationTag` and
478`net::MutablePartialNetworkTrafficAnnotationTag` can be used which do not have
rhalavati@chromium.orgd7c93b3b2018-01-19 08:39:07479this limitation.
Nicolas Ouellet-Payeur35662942021-08-03 16:01:37480
rhalavati@chromium.orgd7c93b3b2018-01-19 08:39:07481Mutable annotations have a run time check before being converted into normal
482annotations to ensure their content is valid. Therefore it is suggested that
483they would be used only if there is no other way around it. Use cases are
Nicolas Ouellet-Payeur35662942021-08-03 16:01:37484checked with `auditor.py` to ensure proper initialization values for the
485mutable annotations.
Ramin Halavatic56d1702017-11-30 09:23:01486
487
488## Mojo Interfaces (Advanced)
489
490For serialization of network traffic annotation and partial network traffic
491annotation tags, you can use the mutable mojo interfaces defined in
Nicolas Arciniega15745e22019-10-09 20:42:35492`/services/network/public/mojom`.