blob: 3247c6269f6f66c1c4926828bea9c9b66db9e798 [file] [log] [blame]
Jihwan Marc Kim3e132f12020-05-20 17:33:191// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef NET_COOKIES_COOKIE_INCLUSION_STATUS_H_
6#define NET_COOKIES_COOKIE_INCLUSION_STATUS_H_
7
8#include <string>
9#include <vector>
10
11#include "net/base/net_export.h"
12
13class GURL;
14
15namespace net {
16
17// This class represents if a cookie was included or excluded in a cookie get or
18// set operation, and if excluded why. It holds a vector of reasons for
19// exclusion, where cookie inclusion is represented by the absence of any
20// exclusion reasons. Also marks whether a cookie should be warned about, e.g.
21// for deprecation or intervention reasons.
22class NET_EXPORT CookieInclusionStatus {
23 public:
24 // Types of reasons why a cookie might be excluded.
25 // If adding a ExclusionReason, please also update the GetDebugString()
26 // method.
27 enum ExclusionReason {
28 EXCLUDE_UNKNOWN_ERROR = 0,
29
Lily Chenc42ac752020-11-03 19:16:3630 // Statuses applied when accessing a cookie (either sending or setting):
Jihwan Marc Kim3e132f12020-05-20 17:33:1931
Lily Chenc42ac752020-11-03 19:16:3632 // Cookie was HttpOnly, but the attempted access was through a non-HTTP API.
33 EXCLUDE_HTTP_ONLY = 1,
34 // Cookie was Secure, but the URL was not allowed to access Secure cookies.
35 EXCLUDE_SECURE_ONLY = 2,
36 // The cookie's domain attribute did not match the domain of the URL
37 // attempting access.
38 EXCLUDE_DOMAIN_MISMATCH = 3,
39 // The cookie's path attribute did not match the path of the URL attempting
40 // access.
41 EXCLUDE_NOT_ON_PATH = 4,
42 // The cookie had SameSite=Strict, and the attempted access did not have an
43 // appropriate SameSiteCookieContext.
44 EXCLUDE_SAMESITE_STRICT = 5,
45 // The cookie had SameSite=Lax, and the attempted access did not have an
46 // appropriate SameSiteCookieContext.
47 EXCLUDE_SAMESITE_LAX = 6,
48 // The cookie did not specify a SameSite attribute, and therefore was
49 // treated as if it were SameSite=Lax, and the attempted access did not have
50 // an appropriate SameSiteCookieContext.
Jihwan Marc Kim3e132f12020-05-20 17:33:1951 EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX = 7,
Lily Chenc42ac752020-11-03 19:16:3652 // The cookie specified SameSite=None, but it was not Secure.
Jihwan Marc Kim3e132f12020-05-20 17:33:1953 EXCLUDE_SAMESITE_NONE_INSECURE = 8,
Lily Chenc42ac752020-11-03 19:16:3654 // Caller did not allow access to the cookie.
Jihwan Marc Kim3e132f12020-05-20 17:33:1955 EXCLUDE_USER_PREFERENCES = 9,
cfredric05c78ac2021-01-06 18:10:2656 // The cookie specified SameParty, but was used in a cross-party context.
57 EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT = 10,
Jihwan Marc Kim3e132f12020-05-20 17:33:1958
Lily Chenc42ac752020-11-03 19:16:3659 // Statuses only applied when creating/setting cookies:
60
61 // Cookie was malformed and could not be stored.
cfredric05c78ac2021-01-06 18:10:2662 EXCLUDE_FAILURE_TO_STORE = 11,
Lily Chenc42ac752020-11-03 19:16:3663 // Attempted to set a cookie from a scheme that does not support cookies.
cfredric05c78ac2021-01-06 18:10:2664 EXCLUDE_NONCOOKIEABLE_SCHEME = 12,
Lily Chenc42ac752020-11-03 19:16:3665 // Cookie would have overwritten a Secure cookie, and was not allowed to do
66 // so. (See "Leave Secure Cookies Alone":
67 // https://tools.ietf.org/html/draft-west-leave-secure-cookies-alone-05 )
cfredric05c78ac2021-01-06 18:10:2668 EXCLUDE_OVERWRITE_SECURE = 13,
Lily Chenc42ac752020-11-03 19:16:3669 // Cookie would have overwritten an HttpOnly cookie, and was not allowed to
70 // do so.
cfredric05c78ac2021-01-06 18:10:2671 EXCLUDE_OVERWRITE_HTTP_ONLY = 14,
Lily Chenc42ac752020-11-03 19:16:3672 // Cookie was set with an invalid Domain attribute.
cfredric05c78ac2021-01-06 18:10:2673 EXCLUDE_INVALID_DOMAIN = 15,
Lily Chenc42ac752020-11-03 19:16:3674 // Cookie was set with an invalid __Host- or __Secure- prefix.
cfredric05c78ac2021-01-06 18:10:2675 EXCLUDE_INVALID_PREFIX = 16,
Lily Chenc42ac752020-11-03 19:16:3676 // Cookie was set with an invalid SameParty attribute in combination with
77 // other attributes. (SameParty is invalid if Secure is not present, or if
78 // SameSite=Strict is present.)
cfredric05c78ac2021-01-06 18:10:2679 EXCLUDE_INVALID_SAMEPARTY = 17,
Jihwan Marc Kim3e132f12020-05-20 17:33:1980
81 // This should be kept last.
82 NUM_EXCLUSION_REASONS
83 };
84
Ayu Ishiib9f3e6e2020-06-15 20:53:1385 // Reason to warn about a cookie. Any information contained in WarningReason
86 // of an included cookie may be passed to an untrusted renderer.
87 // If you add one, please update GetDebugString().
Jihwan Marc Kim3e132f12020-05-20 17:33:1988 enum WarningReason {
89 // Of the following 3 SameSite warnings, there will be, at most, a single
90 // active one.
91
92 // Warn if a cookie with unspecified SameSite attribute is used in a
93 // cross-site context.
94 WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT = 0,
95 // Warn if a cookie with SameSite=None is not Secure.
96 WARN_SAMESITE_NONE_INSECURE = 1,
97 // Warn if a cookie with unspecified SameSite attribute is defaulted into
98 // Lax and is sent on a request with unsafe method, only because it is new
99 // enough to activate the Lax-allow-unsafe intervention.
100 WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE = 2,
101
102 // The following warnings indicate that an included cookie with an effective
103 // SameSite is experiencing a SameSiteCookieContext::|context| ->
104 // SameSiteCookieContext::|schemeful_context| downgrade that will prevent
105 // its access schemefully.
106 // This situation means that a cookie is accessible when the
107 // SchemefulSameSite feature is disabled but not when it's enabled,
108 // indicating changed behavior and potential breakage.
109 //
110 // For example, a Strict to Lax downgrade for an effective SameSite=Strict
111 // cookie:
112 // This cookie would be accessible in the Strict context as its SameSite
113 // value is Strict. However its context for schemeful same-site becomes Lax.
114 // A strict cookie cannot be accessed in a Lax context and therefore the
115 // behavior has changed.
116 // As a counterexample, a Strict to Lax downgrade for an effective
117 // SameSite=Lax cookie: A Lax cookie can be accessed in both Strict and Lax
118 // contexts so there is no behavior change (and we don't warn about it).
119 //
120 // The warnings are in the following format:
121 // WARN_{context}_{schemeful_context}_DOWNGRADE_{samesite_value}_SAMESITE
122 //
123 // Of the following 5 SameSite warnings, there will be, at most, a single
124 // active one.
125
126 // Strict to Lax downgrade for an effective SameSite=Strict cookie.
127 // This warning is only applicable for cookies being sent because a Strict
128 // cookie will be set in both Strict and Lax Contexts so the downgrade will
129 // not affect it.
130 WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE = 3,
131 // Strict to Cross-site downgrade for an effective SameSite=Strict cookie.
132 // This also applies to Strict to Lax Unsafe downgrades due to Lax Unsafe
133 // behaving like Cross-site.
134 WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE = 4,
135 // Strict to Cross-site downgrade for an effective SameSite=Lax cookie.
136 // This also applies to Strict to Lax Unsafe downgrades due to Lax Unsafe
137 // behaving like Cross-site.
138 WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE = 5,
139 // Lax to Cross-site downgrade for an effective SameSite=Strict cookie.
140 // This warning is only applicable for cookies being set because a Strict
141 // cookie will not be sent in a Lax context so the downgrade would not
142 // affect it.
143 WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE = 6,
144 // Lax to Cross-site downgrade for an effective SameSite=Lax cookie.
145 WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE = 7,
146
Maks Orlovichbd04d782020-11-17 21:23:34147 // Advisory warning attached when a Secure cookie is accessed from (sent to,
148 // or set by) a non-cryptographic URL. This can happen if the URL is
149 // potentially trustworthy (e.g. a localhost URL, or another URL that
150 // the CookieAccessDelegate is configured to allow).
151 // TODO(chlily): Add metrics for how often and where this occurs.
Lily Chen14708712020-11-19 16:17:42152 WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC = 8,
Maks Orlovichbd04d782020-11-17 21:23:34153
cfredrica5fb0982021-01-09 00:18:01154 // The cookie was treated as SameParty. This is different from looking at
155 // whether the cookie has the SameParty attribute, since we may choose to
156 // ignore that attribute for one reason or another. E.g., we ignore the
157 // SameParty attribute if the site is not a member of a nontrivial
158 // First-Party Set.
159 WARN_TREATED_AS_SAMEPARTY = 9,
160
161 // The cookie was excluded solely for SameParty reasons (i.e. it was in
162 // cross-party context), but would have been included by SameSite. (This can
163 // only occur in cross-party, cross-site contexts, for cookies that are
164 // 'SameParty; SameSite=None'.)
165 WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE = 10,
166
167 // The cookie was included due to SameParty, even though it would have been
168 // excluded by SameSite. (This can only occur in same-party, cross-site
169 // contexts, for cookies that are 'SameParty; SameSite=Lax'.)
170 WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE = 11,
171
Lily Chenef77a172021-02-22 22:42:26172 // The cookie was SameSite=Lax (or unspecified-treated-as-lax) and was
173 // excluded due to the fix for crbug.com/1166211, i.e. it was accessed by an
174 // HTTP request which was not a main frame navigation, whose initiator was
175 // cross-site and whose site-for-cookies was same-site with the request URL.
176 // TODO(crbug.com/1166211): Remove when no longer needed.
177 WARN_SAMESITE_LAX_EXCLUDED_AFTER_BUGFIX_1166211 = 12,
178
Jihwan Marc Kim3e132f12020-05-20 17:33:19179 // This should be kept last.
180 NUM_WARNING_REASONS
181 };
182
183 // These enums encode the context downgrade warnings + the secureness of the
184 // url sending/setting the cookie. They're used for metrics only. The format
185 // is {context}_{schemeful_context}_{samesite_value}_{securness}.
186 // NO_DOWNGRADE_{securness} indicates that a cookie didn't have a breaking
187 // context downgrade and was A) included B) excluded only due to insufficient
188 // same-site context. I.e. the cookie wasn't excluded due to other reasons
189 // such as third-party cookie blocking. Keep this in line with
190 // SameSiteCookieContextBreakingDowngradeWithSecureness in enums.xml.
191 enum ContextDowngradeMetricValues {
192 NO_DOWNGRADE_INSECURE = 0,
193 NO_DOWNGRADE_SECURE = 1,
194
195 STRICT_LAX_STRICT_INSECURE = 2,
196 STRICT_CROSS_STRICT_INSECURE = 3,
197 STRICT_CROSS_LAX_INSECURE = 4,
198 LAX_CROSS_STRICT_INSECURE = 5,
199 LAX_CROSS_LAX_INSECURE = 6,
200
201 STRICT_LAX_STRICT_SECURE = 7,
202 STRICT_CROSS_STRICT_SECURE = 8,
203 STRICT_CROSS_LAX_SECURE = 9,
204 LAX_CROSS_STRICT_SECURE = 10,
205 LAX_CROSS_LAX_SECURE = 11,
206
207 // Keep last.
208 kMaxValue = LAX_CROSS_LAX_SECURE
209 };
210 // Makes a status that says include and should not warn.
211 CookieInclusionStatus();
212
213 // Make a status that contains the given exclusion reason.
214 explicit CookieInclusionStatus(ExclusionReason reason);
215 // Makes a status that contains the given exclusion reason and warning.
216 CookieInclusionStatus(ExclusionReason reason, WarningReason warning);
217
218 bool operator==(const CookieInclusionStatus& other) const;
219 bool operator!=(const CookieInclusionStatus& other) const;
220
221 // Whether the status is to include the cookie, and has no other reasons for
222 // exclusion.
223 bool IsInclude() const;
224
225 // Whether the given reason for exclusion is present.
226 bool HasExclusionReason(ExclusionReason status_type) const;
227
Lily Chen70c537a2020-07-20 18:02:09228 // Whether the given reason for exclusion is present, and is the ONLY reason
229 // for exclusion.
230 bool HasOnlyExclusionReason(ExclusionReason status_type) const;
231
Jihwan Marc Kim3e132f12020-05-20 17:33:19232 // Add an exclusion reason.
233 void AddExclusionReason(ExclusionReason status_type);
234
235 // Remove an exclusion reason.
236 void RemoveExclusionReason(ExclusionReason reason);
237
cfredric05c78ac2021-01-06 18:10:26238 // Remove multiple exclusion reasons.
239 void RemoveExclusionReasons(const std::vector<ExclusionReason>& reasons);
240
Jihwan Marc Kim3e132f12020-05-20 17:33:19241 // If the cookie would have been excluded for reasons other than
242 // SAMESITE_UNSPECIFIED_TREATED_AS_LAX or SAMESITE_NONE_INSECURE, don't bother
243 // warning about it (clear the warning).
244 void MaybeClearSameSiteWarning();
245
246 // Whether to record the breaking downgrade metrics if the cookie is included
247 // or if it's only excluded because of insufficient same-site context.
248 bool ShouldRecordDowngradeMetrics() const;
249
250 // Whether the cookie should be warned about.
251 bool ShouldWarn() const;
252
253 // Whether the given reason for warning is present.
254 bool HasWarningReason(WarningReason reason) const;
255
256 // Whether a schemeful downgrade warning is present.
257 // A schemeful downgrade means that an included cookie with an effective
258 // SameSite is experiencing a SameSiteCookieContext::|context| ->
259 // SameSiteCookieContext::|schemeful_context| downgrade that will prevent its
260 // access schemefully. If the function returns true and |reason| is valid then
261 // |reason| will contain which warning was found.
262 bool HasDowngradeWarning(
263 CookieInclusionStatus::WarningReason* reason = nullptr) const;
264
265 // Add an warning reason.
266 void AddWarningReason(WarningReason reason);
267
268 // Remove an warning reason.
269 void RemoveWarningReason(WarningReason reason);
270
271 // Used for serialization/deserialization.
272 uint32_t exclusion_reasons() const { return exclusion_reasons_; }
273 void set_exclusion_reasons(uint32_t exclusion_reasons) {
274 exclusion_reasons_ = exclusion_reasons;
275 }
276
277 uint32_t warning_reasons() const { return warning_reasons_; }
278 void set_warning_reasons(uint32_t warning_reasons) {
279 warning_reasons_ = warning_reasons;
280 }
281
282 ContextDowngradeMetricValues GetBreakingDowngradeMetricsEnumValue(
283 const GURL& url) const;
284
285 // Get exclusion reason(s) and warning in string format.
286 std::string GetDebugString() const;
287
288 // Checks that the underlying bit vector representation doesn't contain any
289 // extraneous bits that are not mapped to any enum values. Does not check
290 // for reasons which semantically cannot coexist.
291 bool IsValid() const;
292
293 // Checks whether the exclusion reasons are exactly the set of exclusion
294 // reasons in the vector. (Ignores warnings.)
295 bool HasExactlyExclusionReasonsForTesting(
296 std::vector<ExclusionReason> reasons) const;
297
298 // Checks whether the warning reasons are exactly the set of warning
299 // reasons in the vector. (Ignores exclusions.)
300 bool HasExactlyWarningReasonsForTesting(
301 std::vector<WarningReason> reasons) const;
302
303 // Makes a status that contains the given exclusion reasons and warning.
304 static CookieInclusionStatus MakeFromReasonsForTesting(
305 std::vector<ExclusionReason> reasons,
306 std::vector<WarningReason> warnings = std::vector<WarningReason>());
307
308 private:
cfredric2c5cfa62020-11-16 19:59:25309 // Returns the `exclusion_reasons_` with the given `reasons` unset.
310 uint32_t ExclusionReasonsWithout(
311 const std::vector<ExclusionReason>& reasons) const;
312
Jihwan Marc Kim3e132f12020-05-20 17:33:19313 // A bit vector of the applicable exclusion reasons.
314 uint32_t exclusion_reasons_ = 0u;
315
316 // A bit vector of the applicable warning reasons.
317 uint32_t warning_reasons_ = 0u;
318};
319
320NET_EXPORT inline std::ostream& operator<<(std::ostream& os,
321 const CookieInclusionStatus status) {
322 return os << status.GetDebugString();
323}
324
cfredric34ed01a82020-12-08 05:43:56325// Provided to allow gtest to create more helpful error messages, instead of
326// printing hex.
327inline void PrintTo(const CookieInclusionStatus& cis, std::ostream* os) {
328 *os << cis;
329}
330
Jihwan Marc Kim3e132f12020-05-20 17:33:19331} // namespace net
332
333#endif // NET_COOKIES_COOKIE_INCLUSION_STATUS_H_