0

Let's say I have a Chrome extension adding some JS code to each visited page (this is quite common with content_scripts):

{
    "name": "...",
    "content_scripts": [
        {
            "js": ["run.js"],
            "matches": ["http://*/*", "https://*/*"],
            "run_at": "document_end"
        }
    ]
    ...
}

Let' say the run.js has a global templates variable:

var templates = {0: 'hello world', 1: 'bye bye'}; // default templates

chrome.storage.sync.get("templates", function(obj) {
    templates = obj.templates;
});

document.addEventListener("keydown", function(e) {
    // add template to textarea if a specific key is pressed
}

Question: can a website I'm visiting scrape all my personal data stored in my templates (because it's in a global variable templates), and send it via AJAX to their server? If so, how?

Or is it impossible because there is an isolation wall between Chrome extension content_scripts' variables and the page's variables?

Basj
  • 41,386
  • 99
  • 383
  • 673
  • Note: I already read: [Do content scripts run in the same isolated world, or in separate isolated worlds?](https://stackoverflow.com/questions/29333350/do-content-scripts-run-in-the-same-isolated-world-or-in-separate-isolated-world) but it's unclear what happens in the specific case I described. – Basj Jul 02 '18 at 21:28

1 Answers1

2

Isolated Worlds

No, the context scripts are sandboxed and can only access the DOM, as you can read on the docs:

Content scripts live in an isolated world, allowing a content script to makes changes to its JavaScript environment without conflicting with the page or additional content scripts.

The website you inject run.js to won't be able to access templates.

Actually, even if you do window.templates = templates in run.js, the injected page will get undefined if it tries to access it.

️ Practical Example

Let's say you have a Chrome extension that injects a script on the currently active tab when you press the browser action button that shows a popup on the page. If that popup has already been injected before, you want to just call a toggle method on it.

You could have something like this on your injected script:

import { Popup } from './components/popup.component';

const popup = window.POPUP;

if (popup) {
    popup.toggle();
} else {
    window.POPUP = new Popup();
}

Then:

  • The first time this is injected, window.POPUP, in the world of the context scripts, would be undefined, so we will create a new Popup instance and assign it to window.POPUP, again, in the context scripts' world.

  • The second and subsequent times this is injected, window.POPUP, in the world of the context scripts, would already have a value and we will just call popup.toggle().

  • If a script on the injected page tries to access window.POPUP anytime, in its own world, it will get undefined.

  • If the injected page had a window.POPUP = true, the content script will still get undefined when accessing window.POPUP for the first time, as those two window.POPUP live in separated worlds.

Danziger
  • 19,628
  • 4
  • 53
  • 83
  • @Basj Sorry, I copied the wrong text from the docs. Please, take a look now. I have also added a practical example of what would happen when either the context script or the injected page try to access stuff from the other. – Danziger Jul 02 '18 at 21:58