-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Detect static securecookies to trivialize more rules #16029
Conversation
@cschanaj Can you please explain in prose what rules you're using / when it's going to assume that cookies are ok? I believe this is quite tricky to detect statically but I might be wrong and hard to understand the nuances from code. |
@RReverser This PR aims to trivialize rulesets that would have been modified if securecookies are ignored. It is assumed that if all securecookies are static, they can be safely ignored. A securecookie is called to be static either it is a trivial securecookie or ALL of the following conditions are satisfied:
P.S. I have force-pushed 917e627 because there was an logic error in the previous implementation. Sadly we cannot trivialize the securecookies anyway. P.S.2. When running this commit against the master, it is found that the script is problematic for |
@cschanaj, it would be useful to have this info somewhere else than a comment in this PR. It would be great if you could copy your text from #16029 (comment) in either the commit message or a standalone README. |
This PR aims to trivialize rulesets that would have been modified if securecookies are ignored. It is assumed that if all securecookies are static, they can be safely ignored. A securecookie is called to be static either it is a trivial securecookie or ALL of the following conditions are satisfied: 1. securecookie.host match cookie.host from the beginning ^ to the end $. Otherwise, it might match subdomains/ partial patterns, thus a non-trivial securecookie. 2. securecookie.host will not throw an error when passed to explodeRegExp(). Otherwise, it might match patterns too complicated for our interests. 3. Each exploded securecookie.host should be included in ruleset.target/ exploded target. Otherwise, this ruleset is likely problematic itself. It is dangerous for a rewrite.
@cschanaj I see that you, for example, assume that Also I wonder how you treat cookies on subdomains? In general, |
@RReverser For cookies to be covered, there must be at least one rule covering the same domain. This is guarantee in Trivial securecookie implies that domain list can be trivialized. This also prevent the case where https-everywhere/chromium/background-scripts/rules.js Lines 633 to 659 in a24cc40
|
Ah, that I didn't know. It does change the perspective and optimisation opportunities. Thanks! |
@RReverser could you please confirm this? It seem that not all covered domains are enumerated by |
@cschanaj Do you mean this? diff --git a/src/chrome/content/rules/AllianceBernstein.xml b/src/chrome/content/rules/AllianceBernstein.xml
index 766b024548..db07742ff9 100644
--- a/src/chrome/content/rules/AllianceBernstein.xml
+++ b/src/chrome/content/rules/AllianceBernstein.xml
@@ -11,16 +11,14 @@
-->
<ruleset name="AllianceBernstein (partial)">
+ <target host="bernstein.com" />
<target host="alliancebernstein.com" />
<target host="www.alliancebernstein.com" />
- <target host="bernstein.com" />
- <target host="www.bernstein.com" />
<securecookie host="^(?:www\.)?alliancebernstein\.com$" name=".+" />
- <rule from="^http://(www\.)?(alliance)?bernstein\.com/"
- to="https://$1$2bernstein.com/" />
+ <rule from="^http:" to="https:" />
</ruleset> |
Okay, yes, I found the bug. |
Fix is here: #16051 |
@RReverser yes, thanks for filing a fix!! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Please include a comment in the code as per @Bisaloo's suggestion on what a "static" cookie is, since we're introducing new terminology.
try { | ||
explodeRegExp(securecookie.host, domain => { | ||
if (domain.startsWith('.')) { | ||
domain = domain.slice(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this sufficient munging to ensure it matches the target domains?
If not, at worst it will not match and result in a false
result, which isn't terrible but not desirable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Hainish this should be good enough. As mentioned in #16029 (comment), securecookie.host only match cookie.domain if there is a rule covers cookie.domain. Given the target
are trivial, cookie.domain cannot be anything other than domain.example.com
and .domain.example.com
for a securecookie rule to works. With condition (1) effective, securecookie.host should explode to either one of them. Otherwise, the securecookie will never be applied (dangling rules?) under the current implementation.
With the above logic in mind, I have also add 4bbd731 to remove some of these securecookie rules that will never be effective.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Hainish would you merge this code before the next release if the changes I made after your first review look good to you? So that I can file a separate PR running the script and fix the failing tests. |
@cschanaj yes - releases will be made every other month, so this should be deployed next month. I'll have more time to review next week. No promises if there is a security release, though. |
Perhaps @bcyphers has some time to review? |
Looking at it now |
@RReverser my apologies, I have forgotten to rebase this PR before running the script. the issue is a duplicate of the fixed one. sorry for pinging you. please ignore my previous comment. |
Hi, sorry, still working on this -- had to catch up on the rest of the static simplifications first. I'll have some comments this weekend. |
// safely. | ||
if (unsupportedDomains.size > 0) { | ||
if (unsupportedDomains.size === localDomains.size) { | ||
shouldRemoveSecurecookies = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If any one of the securecookies is unsupported, this will cause all of them to be removed. I don't think that's the intended behavior.
For example, for the following XML, the script will trivialize the file and remove all securecookies:
<target host="a.foo.com" />
<supercookie host="a.foo.com" />
<supercookie host="b.foo.com" />
...
But if the two securecookie entries are combined into one (<securecookie host="^(a|b)\.foo\.com$" />
), the script will refuse to trivialize the XML.
It seems like we should remove one securecookie entry at a time, not drop them all at once. If that's risky (not sure why it would be), we can just refuse to trivialize any XML with unsupported securecookie domains.
See comments in code for more details.
@bcyphers That's indeed unexpected, thanks for catching the bugs 😃 5c149aa should work, I have tested it with the following rulesets; the diff is the result from running the script. <ruleset name="Foo.com">
<target host="*.foo.com" />
<securecookie host="^www\.foo\.com$" name=".+" />
<securecookie host="^a\.foo\.com$" name=".+" />
<rule from="^http://www\.foo\.com/" to="https://www.foo.com/" />
</ruleset> gives 11c11
< <target host="*.foo.com" />
---
> <target host="www.foo.com" />
14,16c14
< <securecookie host="^a\.foo\.com$" name=".+" />
<
< <rule from="^http://www\.foo\.com/" to="https://www.foo.com/" />
---
> <rule from="^http:" to="https:" /> and (noted that the script cannot remove partial dangling securecookie rules) <ruleset name="Bar.com">
<target host="*.bar.com" />
<securecookie host="^(www|a)\.bar\.com$" name=".+" />
<rule from="^http://www\.bar\.com/" to="https://www.bar.com/" />
</ruleset> gives 11c11
< <target host="*.bar.com" />
---
> <target host="www.bar.com" />
15c15
< <rule from="^http://www\.bar\.com/" to="https://www.bar.com/" />
---
> <rule from="^http:" to="https:" />
|
@@ -4,8 +4,8 @@ const { parse } = require('regulex'); | |||
|
|||
class UnsupportedRegExp extends Error {} | |||
|
|||
function explodeRegExp(re, callback) { | |||
(function buildUrls(str, items) { | |||
function explodeRegExp (re, callback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, this file was previously formatted with prettier. Did it add these whitespaces or did you manually? Looks quite odd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think just single-quotes plus semicolons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that prettier will create some strange changes to trivialize-rules.js
, e.g. spliting the back-tick quoted string to the following
+ let scReSrc = `\n([\t ]*)<securecookie\\s*host=\\s*"${escapeStringRegexp(
+ securecookie.host
+ )}"(\\s*)name=\\s*"${escapeStringRegexp(
+ securecookie.name
+ )}"\\s*?/>[\t ]*\n`;
So I guess it is better not to run prettier on it. Would you mind if I leave the file as-is in e8f27ee?
This reverts commit a37df21.
ping @Hainish @bcyphers @RReverser |
if (unsupportedDomains.size === localDomains.size) { | ||
return [true, true]; | ||
} | ||
// TODO: Can we remove partial dangling securecookie rules??? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think so. This means that the author intended at least some of the target domains to use secure cookies, we shouldn't throw out that information
Yeah, I can't find any other issues. I think this is good to go. |
@bcyphers @RReverser @Hainish Thanks for the effort reviewing this PR. linking #16122 |
@bcyphers would you or @Hainish merge this PR? I would like to run this script before the next release and submit a PR to a downstream project in https://github.com/brave/https-everywhere-builder |
@cschanaj sorry this didn't make it in to 2018.8.22. This can be part of the ruleset release next week. |
This PR modify
trivialize-rules.js
to detect staticsecurecookie
to trivialize more rules. It also trivialize thesecurecookie
tags if all thesecurecookie
domain andtarget
domain are strictly identical. This will further trivializes about 100+ rulesets when ran against 8cfabe5cc @RReverser @Hainish @Bisaloo @J0WI