Open
Bug 1493897
Opened 6 years ago
Updated 2 years ago
Considering using user-interaction permission for nsICookieService::BEHAVIOR_LIMIT_FOREIGN
Categories
(Core :: DOM: Security, enhancement)
Core
DOM: Security
Tracking
()
ASSIGNED
People
(Reporter: baku, Assigned: baku)
Details
(Whiteboard: [domsecurity-backlog1] [domsecurity-active])
Attachments
(3 files, 2 obsolete files)
21.41 KB,
patch
|
ehsan.akhgari
:
review+
|
Details | Diff | Splinter Review |
6.90 KB,
patch
|
ehsan.akhgari
:
review+
|
Details | Diff | Splinter Review |
10.74 KB,
patch
|
ehsan.akhgari
:
review+
|
Details | Diff | Splinter Review |
So far, we use cookies to consider a 3rd party context visited or not. What I propose here is the use of the new user-interaction permission. There are 2 important changes compared with the current behavior: 1. a web-site is considered visited if it was previously loaded as first-party and interacted by the user. 2. the current user-interaction permission doesn't consider eTLD+1. Probably this part should change.
Assignee | ||
Comment 1•6 years ago
|
||
Attachment #9011699 -
Flags: review?(ehsan)
Assignee | ||
Comment 2•6 years ago
|
||
I think we should change the permission to be stored for the eTLD+1 instead of the full origin.
Status: NEW → ASSIGNED
Whiteboard: [domsecurity-backlog1] [domsecurity-active]
Comment 3•6 years ago
|
||
Comment on attachment 9011699 [details] [diff] [review] visited_1.patch Review of attachment 9011699 [details] [diff] [review]: ----------------------------------------------------------------- Two things here. 1. Please check in with Tanvi about this change in behavior to make sure she is OK with it too. 2. This shouldn't land without tests... A cursory look around the tree seems to suggest this cookie behavior almost has no tests, and we should really have some... I'd like to look at another version of the patch addressing the comments below. The eTLD+1 issue is important though, let me know if you disagree with what I said below. ::: netwerk/cookie/nsICookieService.idl @@ +89,5 @@ > const uint32_t BEHAVIOR_REJECT = 2; // reject all cookies > + const uint32_t BEHAVIOR_LIMIT_FOREIGN = 3; // reject third-party cookies > + // unless the site has been > + // previously visited and > + // user-interacted. Nit: and interacted with. ::: toolkit/components/antitracking/AntiTrackingCommon.cpp @@ +569,5 @@ > LOG(("Allowing access even though our behavior is reject foreign")); > return true; > } > + > + LOG(("Nothing more to do due to the behavior code %d", Nit: please hardcode BEHAVIOR_REJECT_FOREIGN in the string to make it easier to read. @@ +578,5 @@ > > + if (behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN) { > + nsCOMPtr<nsIPrincipal> principal = > + nsGlobalWindowInner::Cast(aWindow)->GetPrincipal(); > + if (!principal || !AntiTrackingCommon::HasUserInteraction(principal)) { In the beginning of this method we have the following code: nsGlobalWindowInner* innerWindow = nsGlobalWindowInner::Cast(aWindow); nsIPrincipal* toplevelPrincipal = innerWindow->GetTopLevelPrincipal(); if (!toplevelPrincipal) { // We are already the top-level principal. Let's use the window's principal. LOG(("Our inner window lacks a top-level principal, use the window's principal instead")); toplevelPrincipal = innerWindow->GetPrincipal(); } if (!toplevelPrincipal) { // This should not be possible, right? LOG(("No top-level principal, this shouldn't be happening! Bail out early")); return false; } Please change it like this: nsGlobalWindowInner* innerWindow = nsGlobalWindowInner::Cast(aWindow); nsIPrincipal* windowPrincipal = innerWindow->GetPrincipal(); if (!windowPrincipal) { LOG(("Our window has no principal")); return false; } nsIPrincipal* toplevelPrincipal = innerWindow->GetTopLevelPrincipal(); if (!toplevelPrincipal) { // We are already the top-level principal. Let's use the window's principal. LOG(("Our inner window lacks a top-level principal, use the window's principal instead")); toplevelPrincipal = windowPrincipal } MOZ_ASSERT(toplevelPrincipal); Once you have made this change, please remove the definition of the |principal| variable here, and use |windowPrincipal| instead. @@ +579,5 @@ > + if (behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN) { > + nsCOMPtr<nsIPrincipal> principal = > + nsGlobalWindowInner::Cast(aWindow)->GetPrincipal(); > + if (!principal || !AntiTrackingCommon::HasUserInteraction(principal)) { > + LOG(("Nothing more to do due to the behavior code %d", Same nit as above. @@ +585,5 @@ > + *aRejectedReason = nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN; > + return false; > + } > + > + LOG(("Allowing access for visited origin.")); Nit: for visited origin that has been interacted with. @@ +784,5 @@ > LOG(("Allowing access even though our behavior is reject foreign")); > return true; > } > + > + LOG(("Nothing more to do due to the behavior code %d", Same nit as above. @@ +792,5 @@ > } > > + if (behavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN) { > + if (!AntiTrackingCommon::HasUserInteraction(channelPrincipal)) { > + LOG(("Nothing more to do due to the behavior code %d", Same nit as above. @@ +798,5 @@ > + *aRejectedReason = nsIWebProgressListener::STATE_COOKIES_BLOCKED_FOREIGN; > + return false; > + } > + > + LOG(("Allowing access for visited origin.")); Same nit as above. @@ +1194,5 @@ > + } > + > + uint32_t result = 0; > + nsresult rv = > + pm->TestPermissionFromPrincipal(aPrincipal, USER_INTERACTION_PERM, &result); I would like to know more about why you think the permission should be stored at the eTLD+1 level. Note that the permission manager already tests all of the subdomain components of the principal being tested (see https://searchfox.org/mozilla-central/rev/881a3c5664ede5e08ee986d76433bc5c4b5680e6/extensions/cookie/nsPermissionManager.cpp#318), so if the user interaction permission is granted to https://foo.bar.example, https://my.baz.foo.bar.example will be able to set third-party cookies, but https://bar.example wouldn't. That model makes sense to me.
Attachment #9011699 -
Flags: review?(ehsan)
Assignee | ||
Comment 4•6 years ago
|
||
Attachment #9012408 -
Flags: review?(ehsan)
Assignee | ||
Comment 5•6 years ago
|
||
I'm still working on a test. I'll submit a patch tomorrow.
Attachment #9011699 -
Attachment is obsolete: true
Attachment #9012409 -
Flags: review?(ehsan)
Comment 6•6 years ago
|
||
Comment on attachment 9012408 [details] [diff] [review] part 0 - ETLD+1 Review of attachment 9012408 [details] [diff] [review]: ----------------------------------------------------------------- ::: toolkit/components/antitracking/AntiTrackingCommon.cpp @@ +1148,5 @@ > + if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) { > + return; > + } > + > + nsCOMPtr<nsIEffectiveTLDService> eTLDService(do_GetService( It'd be nice to not refetch this from the XPCOM service manager over and over again. Do you mind making this a global StaticRefPtr and obtain the reference once and ClearOnShutdown() it? @@ +1156,5 @@ > + } > + > + nsAutoCString etld1; > + rv = eTLDService->GetBaseDomain(uri, 0, etld1); > + if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS || NS_WARN_IF(NS_FAILED(rv))) { Nit: please break this into two lines. @@ +1169,5 @@ > + // Let's recreate the URL with scheme + base domain. > + nsAutoCString etld1String; > + etld1String.Append(scheme); > + etld1String.AppendLiteral("://"); > + etld1String.Append(etld1); You are losing the port here. Instead of reconstructing the URL manually like this, you should use NS_MutateURI to mutate the URL, set the host on it to the etld+1 and SetPathQueryRef("/"). @@ +1172,5 @@ > + etld1String.AppendLiteral("://"); > + etld1String.Append(etld1); > + > + nsCOMPtr<nsIURI> etld1URI; > + rv = ios->NewURI(etld1String, nullptr, nullptr, getter_AddRefs(etld1URI)); Why not use NS_NewURI so that you don't have to access nsIIOService? @@ +1179,5 @@ > + } > + > + nsCOMPtr<nsIPrincipal> principal = > + BasePrincipal::CreateCodebasePrincipal(etld1URI, > + BasePrincipal::Cast(aPrincipal)->OriginAttributesRef()); Nit: 80 columns please.
Attachment #9012408 -
Flags: review?(ehsan) → review-
Comment 7•6 years ago
|
||
I asked this in comment 3, perhaps you didn't see my question. Besides just reviewing the code, I would like to understand *why* you think we should store this permission at the eTLD+1 level. This means that if the user for example only has a YouTube account and interacts with accounts.google.com as a first-party but uses duckduckgo as their search engine, google.com would get tracking privileges on them. I don't think this is desirable. Can you please explain why we want this?
Flags: needinfo?(amarchesini)
Comment 8•6 years ago
|
||
Comment on attachment 9012409 [details] [diff] [review] part 1 - visited websites Review of attachment 9012409 [details] [diff] [review]: ----------------------------------------------------------------- Thanks! (But please also submit a patch with tests before landing.)
Attachment #9012409 -
Flags: review?(ehsan) → review+
Assignee | ||
Comment 9•6 years ago
|
||
> Can you please explain why we want this?
I wrote that patch to keep the current behavior, where the LIMIT_FOREIGN uses eTLD+1.
I think it's a common approach to have 3rd party elements in separate hosts: cdn.example.com, images.example.com and so on. Maybe we should consider those URLs as visited too?
Flags: needinfo?(tanvi)
Flags: needinfo?(ehsan)
Flags: needinfo?(amarchesini)
Comment 10•6 years ago
|
||
Hmm, yes, that is true. I guess it's fine to allow eTLD+1 based on this reasoning for now, until we come up with an in idea on how to make it stricter.
Flags: needinfo?(ehsan)
Assignee | ||
Comment 11•6 years ago
|
||
Attachment #9012408 -
Attachment is obsolete: true
Attachment #9012598 -
Flags: review?(ehsan)
Comment 12•6 years ago
|
||
Comment on attachment 9012598 [details] [diff] [review] part 0 - ETLD+1 Review of attachment 9012598 [details] [diff] [review]: ----------------------------------------------------------------- Much nicer, thank you. ::: toolkit/components/antitracking/AntiTrackingCommon.cpp @@ +1007,5 @@ > escaped.Append(temp); > > // Stuff the whole thing back into a URI for the permission manager. > nsCOMPtr<nsIURI> topWinURI; > + rv = NS_NewURI(getter_AddRefs(topWinURI), escaped, nullptr, nullptr); No need to pass in the nullptr's explicitly! https://searchfox.org/mozilla-central/rev/ce57be88b8aa2ad03ace1b9684cd6c361be5109f/netwerk/base/nsNetUtil.h#73
Attachment #9012598 -
Flags: review?(ehsan) → review+
Assignee | ||
Comment 13•6 years ago
|
||
Please, take a close look at this change. It seems correct to me, but the test has these numbers which are not always so easy to follow.
Attachment #9018600 -
Flags: review?(ehsan)
Comment 14•6 years ago
|
||
Comment on attachment 9018600 [details] [diff] [review] part 3 - cookie tests Review of attachment 9018600 [details] [diff] [review]: ----------------------------------------------------------------- Thanks! ::: extensions/cookie/test/unit/test_cookies_thirdparty.js @@ +77,5 @@ > Services.cookies.removeAll(); > do_set_single_http_cookie(uri1, channel1, 1); > do_set_cookies(uri1, channel2, true, [2, 3, 4, 5]); > Services.cookies.removeAll(); > + Services.perms.remove(uri1, "storageAccessAPI"); Nit: Services.perms.removeAll(); @@ +125,3 @@ > do_set_cookies(uri1, channel1, true, [0, 1, 1, 2]); > Services.cookies.removeAll(); > // No preference has been set for uri2, but it should act as if Please modify this comment to say that no preference or user-interaction permission has been set for uri2. @@ +135,5 @@ > Services.cookies.removeAll(); > do_set_single_http_cookie(uri1, channel1, 1); > do_set_cookies(uri1, channel2, true, [1, 1, 1, 1]); > Services.cookies.removeAll(); > + Services.perms.remove(uri1, "storageAccessAPI"); Can you please add a similar case to this chunk above where you add the "storageAccessAPI" permission for both uri1 and uri2? Thanks! @@ +144,4 @@ > // LIMIT_THIRD_PARTY overrides > + Services.perms.add(uri1, kPermissionType, > + Ci.nsICookiePermission.ACCESS_LIMIT_THIRD_PARTY); > + do_set_cookies(uri1, channel1, true, [0, 1, 1, 2]); Looks like this change due to the user-interaction permission not being present? Please add a comment above it to state that. @@ +167,5 @@ > > // Test per-site 3rd party cookie limiting with 3rd party cookies disabled > + Services.prefs.setIntPref("network.cookie.cookieBehavior", > + Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN); > + do_set_cookies(uri1, channel1, true, [0, 1, 1, 2]); Same as the above comment (assuming this is the reason for the change, otherwise please state the reason.) @@ +182,5 @@ > > // Test per-site 3rd party cookie limiting with 3rd party cookies limited > + Services.prefs.setIntPref("network.cookie.cookieBehavior", > + Ci.nsICookieService.BEHAVIOR_LIMIT_FOREIGN); > + do_set_cookies(uri1, channel1, true, [0, 1, 1, 2]); Also here.
Attachment #9018600 -
Flags: review?(ehsan) → review+
Comment 15•5 years ago
|
||
There are some r+ patches which didn't land and no activity in this bug for 2 weeks.
:baku, could you have a look please?
Flags: needinfo?(amarchesini)
Comment 17•5 years ago
|
||
baku, is there anything else still needed here, or can I clear my needinfo?
Comment 18•2 years ago
|
||
Clear a needinfo that is pending on an inactive user.
For more information, please visit auto_nag documentation.
Flags: needinfo?(tanvi)
Updated•2 years ago
|
Severity: normal → S3
You need to log in
before you can comment on or make changes to this bug.
Description
•