Last updated: 2020/05/27. Previous update: 2020/04/25. Original document: 2020/04/25
If you're reading this, chances are you're using the Brave browser [https://brave.com/].
Brave is a wonderful privacy-centric browser with some other novel elements.
pxlsFiddle has always been very strong on privacy as well, with full disclosure in its privacy document [/privacy.html] and no third party use or exposure unless explicitly requested by the user through features in the site's operation.
Privacy is a great thing, and the pxlsFiddle author would never suggest that convenience or features should trump privacy by default.
Unfortunately, a specific privacy feature in Brave does cause an incompatibility with the default code base of pxlsFiddle, and this document aims to explain what that feature is, why it is problematic for pxlsFiddle, and how it's being worked around.
Farbling is a term used among Brave developers to denote fuzzing data so that little to no usable information can be collected from it that could be used to identify the browser via so-called fingerprinting methods.
This farbling can mean changing a number ever so slightly, changing audio samples ever so slightly, or changing pixel values ever so slightly.
For canvas element especially, which can be read via code, farbling is intended to thwart fingerprinting issues like detecting which fonts are installed by changing pixel values in the canvas when it is read.
Update 2020/05/27: On 2020/05/18, a blog post by the Brave browser developers[brave.com/whats-brave-done-for-my-privacy-lately-episode-4-fingerprinting-defenses-2-0/] did finally give some public information about farbling.
However, that post appears to erroneously claim that there is a setting where farbling is not applied; neither turning Shields Down nor specifically setting 'all fingerprinting attempts allowed' disables the farbling as far as canvas data-to-blob/dateURL goes.
The post also mentions that this is still in active development, so hopefully that will change.
For canvas elements, when information is read from them through functions such as
.toDataURL("image/png") to turn the canvas into an image (which alters browser UX, is required for uploading to servers, etc.), it means that some pixels will randomly change colors ever so slightly.
Consider these images [pxlsFiddle.com/farbling*.png]):
|canvas||farbled image||farbled pixels highlighted||farbled image (private tab)||farbled pixels highlighted|
While it is not easy to discern in the non-highlighted images, there's a single color value difference in either the red, green, or blue channel. If the color is less than or equal to 255 (the maximum), it adds 1. If it is 255 exactly, it subtracts 1.
Which channel is affected, and which pixels are affected, depends on either the eTLD+1 (in our case, the domain "pxlsFiddle.com") and the content of the canvas (Shields Down), or just the eTLD+1 (Shields Up).
The below is an actual test section for reference and to test future versions of Brave and any other browser that may use farbling.
Update 2020/05/27: The original test no longer automatically detects farbling when Shields are down (it never could with Shields up) with just one invocation of the code, but two seems to do the trick.
pxlsFiddle's Templating tool relies in part on having accurate color values. When converting an image with an arbitrary palette, those pixels are typically matched to those in the palette used on the pxls-style server of choice.
The resulting image should then have perfectly matching colors.
But because of farbling, some of the pixels' colors are actually changed pseudo-randomly. This means that any further processing - manually or automatically - that relies on those colors being accurate will face problems.
Specifically, when the resulting image is used as an input for the template style generator, those farbled pixels would end up with an unhappy face or other default pictograph, and the templating tool would complain that colors do not match the palette.
This is, obviously, not ideal as the pictograph is intended to aid in selecting the correct color from the pxls-style server of choice's palette.
The only way to solve this is by essentially allowing for farbled colors. This effectively means that the code has to allow for an additional 6 variants of each color:
red, green, blue as in the original
red + 1, green, blue where the original red is not saturated (< 255)
red, green + 1, blue where the original green is not saturated
red, green, blue + 1 where the original blue is not saturated
red - 1, green, blue where the original red IS saturated (255)
red, green - 1, blue where the original green IS saturated
red, green, blue - 1 where the original blue IS saturated
As you might imagine, this slows things down, although not by a lot, and thus this is only invoked when the Brave browser has been detected.
Brave offers a feature called 'Brave Shields' that act as an overall toggle for protection measures.
Shields Up means maximum protection is offered.
Shields Down means minimum protection is offered.
Note the use of the word minimum there; some protections still apply, and it appears that this includes canvas farbling.
Update 2020/05/27: This may not be intentional, as a blog post and comments suggest that it should disable when Shields are down.
Honestly, I am not well-versed enough in the matter to know whether fuzzing pixel values as done in Brave is an effective way to help prevent fingerprinting. Given that colors are only minorly changed, it does not appear to provide adequate protection against detecting whether or not a specific font is installed as thresholding on a larger font, image segmentation, and other methods would still have no problem identifying one font from another.
The future appears to be confusing.
On the one hand, one developer is looking to strengthen these protections even further to the point where pxlsFiddle would effectively be broken entirely in Brave.
On the other hand, another developer is suggesting that protections - including fingerprinting protections - be able to be disabled entirely, which should do away with this issue entirely.
As Brave's development continues, this issue will be revisited and the code / this document updated to reflect the state affairs at that time.
( This section was added 2020/05/27 )
Your best bet would be to check with the Brave Browser developers. Here are some use cases encountered in the wild:
Sorry, you're out of luck - at least unless Shields down does, eventually, actually disable this feature as far as the canvas goes.
There's a few options that may work in your scenario.
If the data can be comfortably stored in just 1 channel, consider using the alpha channel, as it is not affected.
If the same except you can't use the alpha channel, store it in all 3 channels. As the farbling is currently only applied to a single channel, the two channels that read back in agreement will have the correct data.
If your data can be encoded as 7 bits (doubling the effective storage required), then those can be stored in the upper 7 bits of the pixel's channel, and the lowest bit that gets farbled can be ignored.
If your data is small enough, you may be able to use an error correcting routine to essentially treat the farbling as random damage to your data, and restore it thusly.
Unfortunately there does not appear to be a good resource to read about farbling in Brave. When this issue was first encountered by one of the pxlsFiddle users, it took some doing to find out what was going wrong, and the pxlsFiddle author's initial response was to file things as a bug report.
Only after extensive google searches did it become clear that "it's not a bug, it's a feature".
The following pages were consulted for code changes and this document:
https://github.com/brave/brave-browser/issues/9186 - Fingerprinting 2.0: Canvas #9186
default protection: farble output, by using eTLD+1 session seed and canvas contents to determine offsets into the canvas to flip randomly selected low order bits
Off: Don't apply any fingerprinting protections
we should extend farbling defenses to protect against fingerprinting approaches with attempt to read pixel-by-pixel info from a canvas
navigator.brave.isBrave() is exposed and can be called.
Brave’s farbling-based fingerprinting protections have three levels, each described in more detail in the following subsections:
Off: no fingerprinting protections are applied
You may just need to ask users to drop shields or disable fingerprinting protections on your site.