When I visit ebay.com for the first time or after cookies clean-up, browser freezes. After a while, browser shows a notification about JShelter being a culprit of the slowdown.
It is probably caused by farbling routine that takes place when calling AudioBuffer.getChannelData(). As this function is called repeatidly many times (1000+), farbling may drastically increase computational complexity of the call. Even my laptop fans kick in when it happens.
Metadata Update from @polcak: - Issue tagged with: broken page
The problem is that farbling takes time. getChannelData is supposed to be fast but we need to iterate through all the data points. There might be many samples that needs to be processed per second in multiple channels.
The research/design issue is if we should change behaviour on such pages. If we do not do any change, users will likely do. Maybe it will change the wrapping and turn AudioBuffering off, maybe they will uninstall the extension. What is the acceptable solution?
I am also thinking on introducing fast but unreliable little lies. We currently do modify all samples. But we can make things faster if we modify only a fraction of samples. Then, the fingerprinter could correlate to the correct value over multiple visits. If the fingerprinter does not invest time into this behaviour, the fingerprint differs. (Currently, ) I think that such behaviour should not be default.
Metadata Update from @polcak: - Issue tagged with: design decision, research
I tried to visit ebay.com with 0.7.1, Recommended level and observed:
So in this case, the audio wrappers are definitely the problem. But we need to face several issues:
I am going to modify the issue title.
Another example is ib.moneta.cz that also performs audio fingerprinting. I am inclined to deactivate Audio fingerprinting farbling by default until we have another solution.
We discussed this issues on the meeting https://lists.nongnu.org/archive/html/js-shield/2022-04/msg00012.html and decided to move the protection to Strict for 0.10. We also received a bug report https://github.com/polcak/jsrestrictor/issues/182. I tried to investigate further and learnt the following:
https://audiofingerprint.openwpm.com/ incorporates code from https://github.com/Valve/fingerprintjs2 (a widely used project). At the time of my testing, getChannelData was accessed on line 168 and 175 each time in a loop:
for (var i = 0; i < evnt.renderedBuffer.length; i++) { sha1.update(evnt.renderedBuffer.getChannelData(0)[i].toString()); }
for (var i = 4500; 5e3 > i; i++) { pxi_output += Math.abs(evnt.renderedBuffer.getChannelData(0)[i]); }
evnt.renderedBuffer.length is 44100 (on the testing computer). So it means that we farble the same array 44100-times during the first loop and 5000-times during the second loop. It takes about 400ms to farble the array on my computer. So it would take about 5.5 hours to run the code.
Possible solutions: 1. Proxy the array and farble on the fly, only the requested items. But JShelter will need to go through the buffer anyway to compute the farbling hash. 2. Or somehow detect that we already farbled the array. But this will likely need to go through the whole array, and compare that with the previously farbled array(s) which will take a lot of time anyway. 3. Looking at the AudioBuffer API https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer, most of the methods do not modify the buffer. The only exception is AudioBuffer.copyToChannel(). So I am thinking to store the results of the farbled calls and invalidate them during calls of AudioBuffer.copyToChannel(). Unfortunately that will need to solve an issue of storing some internal information about the buffer and sharing them between wrappers which we do not do.
I think that only the method no. 3 is a viable solution.
Metadata Update from @polcak: - Issue untagged with: design decision, research - Issue set to the milestone: NLNet evaluation
I investigated further and went for a modified version of 3.
The plan is to ship this version as 0.10 but I will try some experiments tomorrow.
Fix works on eBay and works in jitsy.
Metadata Update from @polcak: - Issue close_status updated to: Fixed - Issue status updated to: Closed (was: Open)