Page 1 of 3

Modifying Navigator Object

Posted: 2021-06-19, 20:52
by RealityRipple
I'm working on an extension to add support for a new function in the "navigator" object, but I can't get it to show up in the window.navigator instances which webpages access, only in the global navigator object or its prototype, which I don't want. Is there any way to modify the navigator object before a window instantiates it or otherwise add to it despite it being read-only?

Re: Modifying Navigator Object

Posted: 2021-06-19, 22:17
by New Tobin Paradigm
I don't think so.

Re: Modifying Navigator Object

Posted: 2021-06-19, 22:51
by Moonchild
Indeed not possible as far as I know. It's a read-only IDL interface, all that's hard-coded.
Why not use your own namespace anyway?

Re: Modifying Navigator Object

Posted: 2021-06-19, 22:58
by RealityRipple
Moonchild wrote:
2021-06-19, 22:51
Why not use your own namespace anyway?
Because I'm implementing a draft spec, not creating something private, and the spec says the function should be a child of a new object in "navigator". It's a really shitty spec, anyway, tho.

Re: Modifying Navigator Object

Posted: 2021-06-19, 23:09
by Moonchild
It'd probably help if you'd be less vague about what you're trying to implement ;)

Re: Modifying Navigator Object

Posted: 2021-06-19, 23:22
by RealityRipple

Re: Modifying Navigator Object

Posted: 2021-06-19, 23:24
by New Tobin Paradigm
What garbage..

Re: Modifying Navigator Object

Posted: 2021-06-19, 23:29
by RealityRipple
Like I said. However, it's better than the bottom third of every page being covered by a banner, so I figured I'd get something that can say "no" to sites that might end up supporting it as soon as I could.

Edit: Their site has a Firefox WebExtension mockup which does some of the most nasty JS proxying ever. If I were an AV suite, I'd mark that code as malicious. Literally funnels all page scripting through a function just so it can overwrite navigator.

Re: Modifying Navigator Object

Posted: 2021-06-20, 03:43
by seadragon
I don't believe this is any kind of web standard (now)... You can wait until other browsers implement it, if they do.

Re: Modifying Navigator Object

Posted: 2021-06-20, 07:10
by Moonchild
RealityRipple wrote:
2021-06-19, 23:29
it's better than the bottom third of every page being covered by a banner,
Sites will do that anyway (despite this implementation) to cover their ass because CEOs who don't know will tell their web people to.

Re: Modifying Navigator Object

Posted: 2021-06-24, 19:56
by RealityRipple
I think I found a safe way to do this:

Code: Select all

var cls =
{
 init: function()
 {
  observerService.addObserver(cls.documentCreated, 'content-document-global-created', false);
 },
 documentCreated:
 {
  observe: function(subject, topic, data)
  {
   if (topic !== 'content-document-global-created')
    return;
   if (!(subject instanceof Window))
    return;
   if (!(subject.navigator instanceof Navigator))
    return;
   let nav = Components.utils.waiveXrays(subject.navigator);
   let dpc = {
    request: function(consentRequestsList)
    {
     let p = new subject.Promise((resolve, reject) => {
      resolve('dummy');
     });
     return p;
    }
   };
   let dpclone = Components.utils.cloneInto(dpc, nav, {cloneFunctions: true});
   nav.dataProtectionControl = dpclone;
  }
 }
}
addEventListener('load', cls.init, false);

Re: Modifying Navigator Object

Posted: 2021-06-25, 00:16
by Moonchild
Just be sure you fully understand the impact of waiveXrays().

Re: Modifying Navigator Object

Posted: 2021-06-25, 00:26
by RealityRipple
Yeah, it's pretty scary. But as long as it's only passed around directly from function to function, and not used as the parent of anything, no other extensions should be able to access it, let alone content code. I think. Promises don't have a "parent" property, do they? Pretty sure that would be the only place it would potentially get dicey.

Re: Modifying Navigator Object

Posted: 2021-06-25, 00:35
by Moonchild
Yeah just makes sure you aren't using it on anything that has sensitive stuff in it or its children. Waiving Xrays is transitive. So... NEVER use it on a global or window object, or something that inherits a global or window object or you'll expose internal/chrome APIs to content and that is something you want to avoid at all costs. So please examine closely what "subject" you pass in here. I'd be more at ease if you actually do a sanity check on the subject first so that nothing else can be passed into that function and have its Xray vision waived. (i.e.: check if the subject is what you expect and bail with an error otherwise, so no other code can abuse your extension as a security hole).

Re: Modifying Navigator Object

Posted: 2021-06-25, 00:59
by RealityRipple
Ah shit. Subject's an nsIDOMWindow for content-document-global-created. I'll have to see exactly what needs to get through Xray vision and just waive that object/those objects.

Edit: Switched to waiveXrays(subject.navigator) instead. It triggers a
Security wrapper denied access to property "then" on privileged Javascript object. Support for exposing privileged objects to untrusted content via __exposedProps__ is being gradually removed - use WebIDL bindings or Components.utils.cloneInto instead. Note that only the first denied property access from a given global object will be reported.
warning but the destination page still gets the result as expected. If I can make the promise on a content object instead of the window, maybe it'll silence it...

Re: Modifying Navigator Object

Posted: 2021-06-25, 02:09
by Moonchild
You create the promise as subject.Promise which is a promise on the nsIDOMWindow object. So that is outside of the transitive scope. If you fix that (somehow!) then I guess you'll be avoiding privilege bleed and the warning would go away.

Re: Modifying Navigator Object

Posted: 2021-06-25, 02:37
by RealityRipple
I was hoping either "content" or "subject.content" would point to the document's context of "window" rather than chromespace's. It appears they do not. This is gonna be annoying.

Edit:
I just tried passing the window object from the page's javascript as a second parameter to request(), and got the same warning. The console printout of it also looks pretty identical to subject.

The weird thing is I'd expect not to get a return value in the page script if it actually denied access to the "then" property like it says, but the response is spit out just fine, before the warning even.

Even weirder, when I actually use ".then()", no warning shows up. Only when I use "await". Something to do with the context of async/await's underlying system?

Re: Modifying Navigator Object

Posted: 2021-06-25, 08:10
by Moonchild
Why are you using promises anyway for this?

Re: Modifying Navigator Object

Posted: 2021-06-25, 14:45
by RealityRipple
The request() function has to be async by spec (and so it waits while the user is shown a doorhanger or prompt dialog). I can't define request() as a normal async function because its "then" doesn't get exposed to the content script at all if I do.

Off-topic:
Tbh I'm thinking this is already more trouble than it's worth for this shit demi-standard, even if you can do fun things like this with it:

Image

Re: Modifying Navigator Object

Posted: 2021-06-25, 16:53
by New Tobin Paradigm
Wait a fucking minute. You are spawning doorhangers from isolated content code?