-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FireMonkey] GM.fetch
doesn't work when privacy.firstparty.isolate
is true
#431
Comments
I can pass const cookies = await browser.cookies.getAll({url, storeId, firstPartyDomain: null}); Update: Feedback needed .... |
I didn't receive new version through updates yet. But I have some thoughts about fix to share. I was heavily leaning on your understanding of First-party isolation. Honestly, event after reading in various sources about it, I still don't fully understand its' mechanism. Exactly the same as, I believe, you are. But I think, that passing I suggest to revert this behavior. Let New global settingAs First-party isolation is important to extension user, ability to make decision about set of cookies to pass with So there could be several layers, where
Or maybe just function would be enough. Difference between object and function is the difference between static and dynamic decision. But function can just return static object (independently of function parameters). Object returned by user should be sanitized, so that only Script author should not be able to (unobservably) overcome First-party isolation or conform with itIn this case script author doesn't have any power over isolation and all scripts with I think it's for better even if it pushes considerate chunk of work to extension user. If this restriction for script authors should be lifted, in my opinion, it should not be done by allowing to pass parameters to Granting to script author ability to conform with First-party isolation along with transparency of this conforming to user and providing extension user to easily observe and change (restrict) script behavior could be achieved by new For example, // @grant requestCookies {["https://example.com", "firefox-private"]: {firstpartyDomain: "https://example.com", partitionKey: {topLevelSite: 'https://example.com'}} It should be overridible by user in Considering Dynamic state paritioningAccording to cookies API / Tracking protection:
I think, it means, that extension user should be able to control two (and only two) entries in |
v2.45 is not released yet.
|
In implementing support for first-party isolation, please, consider concrete use-case: enabling "[v] Always use private browsing mode" on In this case contextual identity ( See:
Even though passing I might be wrong. Sorry for distraction then. If you'll use the method of providing user-defined JavaScript function, then I want to note, that I didn't really fully think about set of parameters of this function that will be useful for extension user to make decision. It might be useful to additionally pass |
Please note that AFA Firefox contextual identities, Private browsing is a type of contextual identity (e.g. a special type of container), as mentioned under The current situation is:
I am not sure what effect would setting PS. I changed the setting to const cookies = await browser.cookies.getAll({url, storeId, firstPartyDomain: ''}); |
Testconst url = 'https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch';
const storeId = 'firefox-default';
browser.cookies.getAll({url, storeId}); // Array [ {…} ]
browser.cookies.getAll({url, storeId, firstPartyDomain: null}); // Array [ {…} ]
browser.cookies.getAll({url, storeId, firstPartyDomain: ''}); // Array [ {…} ]
browser.cookies.getAll({url, storeId, firstPartyDomain: 'mozilla.org'}); // Array [] const url = 'https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch';
const storeId = 'firefox-private';
browser.cookies.getAll({url, storeId}); // Array []
browser.cookies.getAll({url, storeId, firstPartyDomain: null}); // Array []
browser.cookies.getAll({url, storeId, firstPartyDomain: ''}); // Array []
browser.cookies.getAll({url, storeId, firstPartyDomain: 'mozilla.org'}); // Array [] const url = 'https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch';
const storeId = 'firefox-container-1';
browser.cookies.getAll({url, storeId}); // Array []
browser.cookies.getAll({url, storeId, firstPartyDomain: null}); // Array []
browser.cookies.getAll({url, storeId, firstPartyDomain: ''}); // Array []
browser.cookies.getAll({url, storeId, firstPartyDomain: 'mozilla.org'}); // Array [] |
I think, your tests should include case where
Maybe not so relevant thoughts about distinctive feature of firefox-private containerSpeaking as a FireMonkey user, yes, you are totally right. There is no need to introduce any additional support for Private browsing mode. But speaking as a Firefox user, in broader point of view, Private browsing mode is: 1) a container that could be used without installing additional extensions and 2) a container that automatically deletes cookies etc, i.e. most of storage (if not all) before closing browser. These are weak reasons, because installing FireMonkey means that other extensions also could be installed (Temporary Containers, Cookie AutoDelete or others). Still, Private browsing mode is provided by browser developers and might be integrated in user experience and tested better than extensions. Anyway, this is probably tangential to First-party isolation issues. My thoughts were wandering somewhere but I just don't want to delete this text. First-party isolationI think this feature was proposed in Firefox bug #65965. Quoting from it:
Comment 35 on this bug says:
What First-party isolation (FPI) doesFPI could be seen as an automatic "container" (or "sub-container" when actual container is used) with the name computed from hostname (and in some cases also from scheme and port). It contains at least third-party cookies. Without FPI:
With FPI:
What it means for
|
It doesn't contradict what I said, although I meant from the browser API point of view of contextual identity e.g. the method FPI & cookies.getAll in FireMonkey
AFA I understand the situation, FPI relates mostly to the browsing behaviour which is not the same for FM HTTP request behaviour. Based on the above scenario:
FM HTTP request to
|
Overall, I agree that script author shouldn't be restricted in using HTTP requests basing on browsing behavior. But in this situation user expectations should be also considered.
In my current understanding of containers and first-party isolation, theirs' expected outcomes are mostly the same. Both are providing an element to the set of "origin attributes". When browser looks for data by origin, it also uses these origin attributes. (These examples were edited, because I was using
(Resulting strings of "modified" origin are not the exact representations, but they are close enough to illustrate the described behavior.). So if FireMonkey limits access to cookies basing on I want to stress again, that Not using Though using |
I am not sure the example covers the situation. TAB that userscript inserted into
Userscript GM HTTP Request from above tab
|
Given that first-party isolation is disabled, Why Given that first-party isolation is enabled by user, why is When user creates new container, he expects that cookies from other containers will not leak into current (new) container. Passing Maybe But still passing When user enables first-party isolation and loads Note that userscript acts on behalf of user, not on behalf of script author. Script author doesn't care about what cookies are passed to URL requested from userscript. Script author doesn't care about user privacy. User (with enabled first-party isolation) cares about own privacy a lot. So if If But if |
I have been asking Mozilla engineers for verification. Here is my latest query:
|
If you know what to set browser.cookies.getAll({url, storeId, firstPartyDomain: ''}); |
Revert it to browser.cookies.getAll({url, storeId}); and leave it be. Otherwise, look at Firefox code for the right answer. Exact value of There are two such algorithms (first is a subset of second):
For example, in case when
(But algorithm is not so simple as: just take second-level domain. At least not in all cases.) If |
No problem ...
That doesn't relate to Here is the process:
Where does |
First-party isolation is a tracking protection. It matters when Without first-party isolation:
But with first-party isolation, when I visit Then. when I'll visit The same logic must apply to userscript request made on behalf of user in context of concrete tab. Otherwise it just doesn't meet expectations and guarantees that first-party isolation satisfies and provides. Speaking bluntly, passing Let me describe an example in slightly changed way:
|
OK... how can the desired outcome be achieved?
So, what shall be done in |
Value of
|
Parameters in PopulateTopLevelInfoFromURI are not available to extensions. Since |
Can you describe what it means in terms of code? All changes made for "supporting" first-party isolation are reverted and now
They will not be enabled by default in Firefox ever. However, dynamic first-party isolation (state partitioning + total cookie protection) is already exposed through There is an extensive discussion of what dFPI is in arkenfox/user.js#1051. Citation from arkenfox/user.js#1051 (comment)Thorin-Oakenpants commented on Mar 29, 2021
Dynamic first-party isolation is related to
Of course, they are not. But their values can be deduced and either ignored (as irrelevant), or got by extension through standard APIs, or requested by extension from user (providing knobs in FireMonkey settings).
It might be productive to reference this issue and ask Mozilla to expose algorithm of computing |
Yes, I reverted the code back to what it was as per #issuecomment-1058365410. I have already asked Mozilla engineers for the proper way to set I am happy to implement the feature, and open to suggestions on how to actually implement it (i.e. the code). |
Thank you.
They pointed in right direction, but in my opinion that information on MDN is insufficient to find how to determine required values in different contexts of multiple sites which URLs will be known only after user browsed to them.
I believe I can try to provide you with translation of C++ function to JavaScript function (and supporting JavaScript code) in form of patch to FireMonkey code. But there is a licensing issue. As I understand, you distribute FireMonkey source code only through A bigger issue with licensing is that translation of algorithm from Firefox C++ source code to JavaScript code will be a derivative work and it should be attributed so and licensed as Firefox C++ code. Is Firefox code license compatible with your extension code license? The only way to be sure for me is to read LICENSE explicitly distributed by you along with FireMonkey source code. To put it straight: it's possible that I will not be able to contribute a patch even after including LICENSE, but in absence of LICENSE compatible with Firefox source code, I will certainly not contribute it. It's not an ultimatum, I'm fine with current situation. Just trying to make this situation clear. But there could be an easier way (if only taking more time to get through) without any licensing issues. Try to refer to this issue and ask Mozilla to implement In this case you will be able to just merge this returned object to |
As per AMO page, FireMonkey is distributed under Mozilla Public License 2.0 Open Source Licence. Getting BTW, have you tested the actual result with Is there any other userscript manager or other addon that is implementing a similar feature? |
I have been thinking about this. TBH, it should not be necessary to use an algorithm to deduce values for in A setting that no one knows what value it should have, is no help. |
I noted your thoughts, but I will answer to your comments sometime later, because for now I want to discuss patch workflow. I've created a gist (https://gist.github.com/leonidborisenko/5f38c1cd3b38404fa5979dfc05516c37) with I will update gist in process of further work and post update pings here. Is this workflow suitable for you? |
Where is Some parts are not necessary for FireMonkey since:
|
J have been talking with Mozilla engineers and ......... erosman
Reply
erosman
Reply
erosman
Reply
erosman
Reply
Test(() => {
const url = 'https://greasyfork.org/en';
browser.cookies.getAll({url})
.then(c => console.log('no-fpd', c))
.catch(console.log);
browser.cookies.getAll({url, firstPartyDomain: ''})
.then(c => console.log('empty-fpd', c))
.catch(console.log);
browser.cookies.getAll({url, firstPartyDomain: null})
.then(c => console.log('null-fpd', c))
.catch(console.log);
browser.cookies.getAll({url, firstPartyDomain: 'google.com'})
.then(c => console.log('domain-fpd', c))
.catch(console.log);
})(); Result// privacy.firstparty.isolate: false
no-fpd Array(3) [ {…}, {…}, {…} ]
empty-fpd Array(3) [ {…}, {…}, {…} ]
null-fpd Array(5) [ {…}, {…}, {…}, {…}, {…} ]
domain-fpd Array []
// privacy.firstparty.isolate: true
Error: First-Party Isolation is enabled, but the required 'firstPartyDomain' attribute was not set.
empty-fpd Array(3) [ {…}, {…}, {…} ]
null-fpd Array(5) [ {…}, {…}, {…}, {…}, {…} ]
domain-fpd Array [] Besides the error in 2nd test with Can you run the test (from FireMonkey Toolbox via |
When Firefox selects cookies for the purpose of sending them in HTTP(S) request initiated by Firefox itself in context of browser tab, it automatically computes and uses But when HTTP(S) request is made from FireMonkey background page, Firefox doesn't know the exact tab where this request is actually started, so if FireMonkey wants to select cookies with providing first-party isolation guarantees, then
Do you understand why For example, do you agree that when
(Because Do you understand why there are two domains in Principal and how first domain should be determined? Do you understand how Principal value is used by Firefox for selecting cookies from cookie jar to send in HTTP request? How Principal will look when FPI is disabled? Without FPI Firefox uses only And computing When FPI is disabled, then When FPI is enabled, then real first-party isolation is provided by getting cookies with And with this, I believe, there is no common ground between us to discuss results of your tests. While I did describe my understanding of FPI mechanism and scenarios when FPI effect can be observable, you didn't. You can find mistakes in my reasoning without me even performing any tests, but I can't find any mistakes in your reasoning, because you didn't provide any reasoning that your tests were founded on. It's not a fault per se, but if you want discussion, then I just struggle to understand:
|
I've finished patch. There is no need for additional permissions, because I use heuristics to determine enabled method of cookies isolation.
Thanks, I didn't notice that. Now I see that license is also mentioned in descripton on AMO. It's sufficient for me to provide a patch. But it would be nice to include text file with license in distributed XPI and mention name of license in short leading comment in source files.
Well, there is a standard method to get a value for Comment by Firefox contributor from ten months ago (https://bugzilla.mozilla.org/show_bug.cgi?id=1669716#c10):
I totally agree that requiring additional permissions is a no-go. And even Some heuristics can be used to select appropriate behavior and escape hatch can be provided in form of entry in FireMonkey preferences where user can explicitly select currently enabled method of cookie isolation.
No. Issue for Greasemonkey is linked in top post (greasemonkey/greasemonkey#2985). I've created an issue for Violentmonkey (violentmonkey/violentmonkey#1467). Tampermonkey is closed-source now and when it was open-sourced, there was no first-party isolation in Firefox.
It's in
I understand that FireMonkey requires only subset of functionality provided by re-implemented function. But I tried to translate function closer to original implementation, so that any new changes in C++ code could be easily mapped to translated code. I believe, it will help to support this code in future. |
Thank you for the explanation. Therefore, it appears that AFA Please note that while |
My patch doesn't work without additional libraries and |
So, in short: You shouldn't have used it, don't use it anymore and don't complain if stuff breaks if you still do. Please ignore every 2nd privacy-enhancement website still telling you to do so. |
Thanks for your concerns. In fact, amidst discussion of this issue I did extensively research why FPI was implemented. I've summarized my research in gist (see for instance, some of its' sections: 1, 2, 3) linked in #431 (comment). So I am fully able to make my own decisions, whether to use it or not. And I've not only complained about FireMonkey error, but also have provided a patch. Again, see aforementioned gist. I did all I could to minimize amount of work required from FireMonkey author to resolve issue. While reported error doesn't occur when dFPI is used, underlying cause still affects dFPI users. Firefox doesn't automatically apply isolation to HTTP(S) requests made from extensions. It should be done manually by extension author. FireMonkey just blissfully ignores enabled FPI and enabled dFPI. It retrieves and sends cookies from unpartitioned storage when userscript makes request to third-party site. Quote from Browser Extensions > JavaScript APIs > cookies # Storage Paritioning:
Quote from Browser Extensions > JavaScript APIs > cookies > cookies.getAll() # Parameters
My patch implements isolation guarantee (as much as it's possible by using official WebExtension API) and resolves underlying cause for FPI and dFPI users. With this change, reported bug is also fixed. |
@leonidborisenko: Sorry, my bad. I always tell people to only post after they read the whole thing... 🤦 |
Firefox has a "First-party isolation" feature.
privacy.firstparty.isolate
is a setting available inabout:config
.GM.fetch
fails when this feature is enabled. I traced failure tobrowser.cookies.getAll({url, storeId})
call inaddCookie()
function defined incontent/background.js
.According to cookies.getAll() API documentation, it has an optional parameter:
A little bit relevant issue in GreaseMonkey: greasemonkey/greasemonkey #2985
Current workaround (if sending cookies is not required) is to call:
The text was updated successfully, but these errors were encountered: