0

I write a Mozilla Firefox Addon, that lets me comment websites: When I open a website and click somewhere, the plugin creates a <div> box at this location, where I can enter a comment text. Later, when I open the website again, the plugin automatically puts my previously created comment boxes at the places they where before. (Similar to a comment feature in many PDF readers, etc.)

This leads to a security problem: A website could use an event listener to listen to the creation of new <div> elements and read their content, allowing it to read my private comments.

How can I solve this security issue? Basically, I want a Firefox addon to put private content in a website, while the website should not be able to access this content via JavaScript. (Unless I want it to.)

I could listen to listeners and detach them as soon as the website attaches them - but that does sound like a solid solution.

Is there a security concept in order to make my addon the authority over DOM changes, respectively, to control the access to certain elements? Alternatively, would it be possible to implement some sort of overlay, which would not be an actual part of the websites DOM but only accessible by the addon?

Similar security problems should occur with other addons. How do they solve it?

  • Quick and maybe off-topic question: Why an addon rather than a userscript? – Lucio Jan 10 '14 at 07:09
  • 1
    I think having your name automatically injected into every page so the page can steal it is the real security problem. – user229044 Jan 10 '14 at 07:17
  • Thanks for your considerations. The question is not about the purpose of the plugin, but the general principle of changing the DOM without letting the website know. To clarify, I rewrote the question. – Patrick Green Jan 11 '14 at 15:45

4 Answers4

3

If you inject the DOM in a document, the document will always be able to manipulate it, you can't really do much about it. You can either:

1) Don't inject your comment directly in the document, but just a placeholder were there is the first words of the comment, or an image version of the comment (you can generate that with canvas), leave the full ones in your JavaScript Add-on scope, that is not accessible from the page: when you click to edit or add, you can open a panel instead and do the editing there.

2) Inject an iframe, if you have your page remotely in another domain shouldn't be a problem at all, the parent's document can't access to the iframe; but also viceversa: you need to attach content script to your iframe in order to talk with your add-on code, and then you can use your add-on code to send and receive messages from both iframe and parent's document. If you use a local resource:// document, I'm afraid you need a terrible workaround instead, and you need to use sandbox policies to avoid that the parent's document can communicate with the iframe itself. See my reply here: Firefox Addon SDK: Loading addon file into iframe

3) Use CSS: you can apply a CSS to a document via contentStyle and contentStyleFile in page-mods. The CSS attached in this way can't be inspected by the document itself, and you could use content to add your text to the page, without actually adding DOM that can be inspected. So, your style for instance could be:

  span#comment-12::after{
    content: 'Hello World';
  }

Where the DOM you add could be:

  <div><span id='comment-12'></span></div>

If the page tries to inspect the content of the span, it will get an empty text node; and because from the page itself the stylesheet added in this way cannot be inspected, they cannot the styles rules to get the text.

Not sure if there are alternatives, those are the solutions that pop to my mind.

Community
  • 1
  • 1
ZER0
  • 24,846
  • 5
  • 51
  • 54
2

Add-ons that do similar things implement some combination of a whitelist / blacklist feature where the add-on user either specifies which sites they want the action to happen on, or a range of sites they don't want it to happen on. As an add-on author, you would create this and perhaps provide a sensible default configuration. Adblock Plus does something similar.

therealjeffg
  • 5,790
  • 1
  • 23
  • 24
  • Thank you, but I think for some plugins whitelists are not suitable. I rewrote the question in order to show, that in this case the security issue can't really be avoided by implementing a whitelist. – Patrick Green Jan 11 '14 at 15:50
2

Create an iframe and bind all your events to the new DOM. By giving it a different domain to the website, you will prevent them from listening in to events and changes.

Barney
  • 16,181
  • 5
  • 62
  • 76
  • Thanks, an iframe's origin policy is a good solution to restrict access. However, I am not sure how I can still make it accessible by my main plugin script. Could you get a little more into detail? – Patrick Green Jan 12 '14 at 03:09
  • @PatrickGreen I'm afraid I'm not overly familiar with extension programming — [I know it's easy enough with vanilla Javascript](http://stackoverflow.com/questions/2665980/filling-an-iframe-with-dynamic-content-from-javascript); meanwhile [implementing it with XUL](http://stackoverflow.com/questions/18506117/create-mozilla-extension-to-display-a-popup-and-iframe-in-it) and [the add-on SDK](https://gist.github.com/anantn/4430391) seems to be possible. I imagine the exact implementation would depend upon your existing code and other specific concerns… – Barney Jan 14 '14 at 09:40
  • @PatrickGreen meanwhile you can ensure the iframe remains inaccessible by setting the [`document.domain`](https://developer.mozilla.org/en-US/docs/Web/API/document.domain) property to a unique string. – Barney Jan 14 '14 at 09:46
  • According to the API I can only alter `document.domain` within the the subdomain. This would not prevent access by the website, assuming the host also controls its subdomains. – Patrick Green Jan 14 '14 at 13:40
1

Addons can use use the anonymous content API used by the devtools to create its node highlighter overlays.

Although the operations supported on anonymous content are fairly limited, so it may or may not be sufficient for your use-case.

the8472
  • 40,999
  • 5
  • 70
  • 122