Blocking on an API basis

Bug reports and enhancement requests
phyks
Posts: 9
Joined: Fri Mar 27, 2015 8:23 pm

Blocking on an API basis

Post by phyks »

Hi,

I am currently looking for a way to block JavaScript on an API basis, rather than a per script basis, and to allow user to selectively enable the requested APIs on a per-site basis, if needed. One of the main things preventing users from using NoScript (and similar extensions), in my opinion, is that if one block everything, most of the web is actually broken as almost every website need JavaScript to work properly and does not degrade nicely.

I looked for solution to my use case, but did not find any working extension for Firefox to handle it, but maybe I missed something.

For instance, I do not care that any website uses the DOM API and updates the DOM, and would allow it for almost every website. On the contrary, I want to be aware when a website uses other APIs such as clipboard access / webRTC (which is known for leaking private IP when using a proxy) / localStorage and so on. For such sites, I would like to have a box telling me that the visited website requires such APIs, and to ask me whether I want to allow it or not, a bit like what is done with external plugins (such as Flash) in latest Firefox.

What do you think about this and its feasibility? An implementation idea I have is by overriding the base APIs, to redefine them, and exporting them in the global JS namespace.
Mozilla/5.0 (X11; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0
barbaz
Senior Member
Posts: 11066
Joined: Sat Aug 03, 2013 5:45 pm

Re: Blocking on an API basis

Post by barbaz »

phyks wrote:I am currently looking for a way to block JavaScript on an API basis, rather than a per script basis, and to allow user to selectively enable the requested APIs on a per-site basis, if needed. One of the main things preventing users from using NoScript (and similar extensions), in my opinion, is that if one block everything, most of the web is actually broken as almost every website need JavaScript to work properly and does not degrade nicely.
Er.. in my experience plenty of webpages are perfectly usable without allowing their JS...
phyks wrote:On the contrary, I want to be aware when a website uses other APIs such as clipboard access / webRTC (which is known for leaking private IP when using a proxy) / localStorage and so on. For such sites, I would like to have a box telling me that the visited website requires such APIs, and to ask me whether I want to allow it or not, a bit like what is done with external plugins (such as Flash) in latest Firefox.
Isn't asking about usage of webRTC the default in Firefox?

Anyway, hanging site scripts when they don't expect it sounds like asking for trouble... unless you mean block the APIs, notify the user, and offer to reload the page with those APIs unblocked?
phyks wrote:What do you think about this and its feasibility?
It's feasible for most properties, but generally only advanced users who understand the consequences should be playing with it. Such a feature seems way too much of a potential footgun to ship with NoScript.

I think a NoScript surrogate script (or Greasemonkey/Scriptish user script) could do exactly what you're asking for. However the only way I can think to be able to reload the page with some APIs not blocked would be to cache which APIs not to block in the hash portion of the window's location - which is webpage-detectable - and even at that, I think the surrogate have to change the window URL hash portion and then ask you to manually reload. So it's clumsier than an actual extension would be, but possibly could be feasible.
phyks wrote:An implementation idea I have is by overriding the base APIs, to redefine them, and exporting them in the global JS namespace.
Maybe this is just me, but your implementation idea sounds quite complicated compared to the one line of JS I personally use to block individual JS properties. Or maybe my one line of JS is doing pretty much that, dunno :?
*Always* check the changelogs BEFORE updating that important software!
-
phyks
Posts: 9
Joined: Fri Mar 27, 2015 8:23 pm

Re: Blocking on an API basis

Post by phyks »

Many webpages are not usable at all without JavaScript. For example, Discourse sites look completely different with and without JavaScript. https://fiddle.md/ is even worse as it simply displays a blank page and nothing else, if JavaScript is not enabled. Most of the websites I visit have poor design without JavaScript as JavaScript is used to design instead of CSS.

Yes, I meant to block the APIs calls (by overriding them with safe functions for instance), warn the user and ask him whether he want to reload the page with all the APIs or continue to block them. It's basically the same idea as what is done right now in Firefox for Flash for instance.

If it is part of the core browser or of a plugin, it can handle safely the export to override the default APIs, and handle a whitelist / blacklist mechanism, just as NoScript actually does, I think, then it does not need at all a window URL hash hack or so.


Maybe I missed something, but what is your one line of JS to block individual JS properties ?

Thanks
Mozilla/5.0 (X11; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0
barbaz
Senior Member
Posts: 11066
Joined: Sat Aug 03, 2013 5:45 pm

Re: Blocking on an API basis

Post by barbaz »

phyks wrote:Maybe I missed something, but what is your one line of JS to block individual JS properties ?
It's like this template:

Code: Select all

Object.defineProperty(window.navigator, 'sendBeacon', {set:function(){}});
In your case you would want to extend/use it something like as follows: (Warning: untested code)

Code: Select all

let _usedSendBeacon = false;
if (window.location.hash.indexOf('===navigator.sendBeacon') == -1) {
  Object.defineProperty(window.navigator, 'sendBeacon', {
    enumerable: true,
    get:function(){ return function(){
      _usedSendBeacon = true;
      window.setTimeout( function() { confirm('This page wants to use navigator.sendBeacon, allow on next reload?') && window.location.hash += '===navigator.sendBeacon';}, 0);
    }},
  set:function(){}}
}
*Always* check the changelogs BEFORE updating that important software!
-
User avatar
Thrawn
Master Bug Buster
Posts: 3106
Joined: Mon Jan 16, 2012 3:46 am
Location: Australia
Contact:

Re: Blocking on an API basis

Post by Thrawn »

barbaz wrote:cache which APIs not to block in the hash portion of the window's location - which is webpage-detectable
Wouldn't it also be possible for a page to *tamper* with that?
======
Thrawn
------------
Religion is not the opium of the masses. Daily life is the opium of the masses.

True religion, which dares to acknowledge death and challenge the way we live, is an attempt to wake up.
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0
barbaz
Senior Member
Posts: 11066
Joined: Sat Aug 03, 2013 5:45 pm

Re: Blocking on an API basis

Post by barbaz »

Yes it would. However if only one person (phyks) does it, the page won't know what to look for to tamper with. I also think phyks is smart enough to know how to change the hash modification to something other than what I posted :P
*Always* check the changelogs BEFORE updating that important software!
-
phyks
Posts: 9
Joined: Fri Mar 27, 2015 8:23 pm

Re: Blocking on an API basis

Post by phyks »

Ok for the way you handle it.

But, why using the location hash to handle it, and not a dedicated config storage as a plugin / localStorage?


And what about including such features in an advanced tab in NoScript?
Mozilla/5.0 (X11; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0
barbaz
Senior Member
Posts: 11066
Joined: Sat Aug 03, 2013 5:45 pm

Re: Blocking on an API basis

Post by barbaz »

phyks wrote:why using the location hash to handle it, and not a dedicated config storage as a plugin / localStorage?
The reason is just me not thinking of those things :roll:
I've never used them or had occasion to play with them.
phyks wrote:And what about including such features in an advanced tab in NoScript?
No point IMO, adding to/modifying the surrogates is not something many users need or care to do.
*Always* check the changelogs BEFORE updating that important software!
-
phyks
Posts: 9
Joined: Fri Mar 27, 2015 8:23 pm

Re: Blocking on an API basis

Post by phyks »

Something I've just found, how would you address such a thing? https://github.com/diafygi/webrtc-ips/b ... x.html#L41

The iframe trick is really nice and your method does not seem to work to prevent it.

Thanks
Mozilla/5.0 (X11; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0
barbaz
Senior Member
Posts: 11066
Joined: Sat Aug 03, 2013 5:45 pm

Re: Blocking on an API basis

Post by barbaz »

So you're trying to block window.RTCPeerConnection and window.mozRTCPeerConnection right?
What's your sources value for the surrogate?
*Always* check the changelogs BEFORE updating that important software!
-
phyks
Posts: 9
Joined: Fri Mar 27, 2015 8:23 pm

Re: Blocking on an API basis

Post by phyks »

Hi,

Sorry for the delay, I did notice your response.

I managed to override the window.mozRTCPeerConnection object, but I did not find any way to override the trick used here : https://github.com/diafygi/webrtc-ips/b ... x.html#L41

Sadly, it seems to be really difficult to block this trick…
Mozilla/5.0 (X11; Linux x86_64; rv:37.0) Gecko/20100101 Firefox/37.0
barbaz
Senior Member
Posts: 11066
Joined: Sat Aug 03, 2013 5:45 pm

Re: Blocking on an API basis

Post by barbaz »

All right I will host that on my local server and see what can be done about
*Always* check the changelogs BEFORE updating that important software!
-
barbaz
Senior Member
Posts: 11066
Joined: Sat Aug 03, 2013 5:45 pm

Re: Blocking on an API basis

Post by barbaz »

Try a sources value of

Code: Select all

@^(?!chrome:)[0-9A-Za-z-]+:
*Always* check the changelogs BEFORE updating that important software!
-
phyks
Posts: 9
Joined: Fri Mar 27, 2015 8:23 pm

Re: Blocking on an API basis

Post by phyks »

Hmm, here is my extract aout:config:

Code: Select all

noscript.surrogate.test.replacement = window.RTCPeerConnection = false; window.mozRTCPeerConnection = false;
noscript.surrogate.test.sources = @^(?!chrome:)[0-9A-Za-z-]+:;
It works to block the first try to get RTCPeerConnection, but not the later with the iframe trick (linked above).


I may have missed something, but this iframe trick is working even if I block iframes with noscript (which just prevent them from being loaded it seems but still creates the iframe element), which seems to be very bad… And this iframe trick seems to be usable with every JavaScript API, not only RTCPeerConnection.
Mozilla/5.0 (X11; Linux x86_64; rv:37.0) Gecko/20100101 Firefox/37.0
barbaz
Senior Member
Posts: 11066
Joined: Sat Aug 03, 2013 5:45 pm

Re: Blocking on an API basis

Post by barbaz »

phyks wrote:

Code: Select all

noscript.surrogate.test.replacement = window.RTCPeerConnection = false; window.mozRTCPeerConnection = false;
There's the problem. I don't think that will work. You need to use Object.defineProperty() as shown above.
*Always* check the changelogs BEFORE updating that important software!
-
Post Reply