Is Errors.net official extension safe?

High risk

Errors.net official extension is high risk. Dynamic analysis captured 18 POSTs from this extension to errors.net in one session across 5+ sites, each carrying the page's full URL and a persistent install ID. Any 4xx/5xx page also triggered a POST with its URL, keyed to a stable UUID.…

76Risk
Who publishes it

Status 77 - no other listings under this identity, 1 shared hostname

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Jon
Declared legal entity
Status 77
Registered address
325 North Ash Street, 207, Gilbert, AZ 85233, US
Registered contact
Jon Grant
Website

Shared hosts - 1 hostname

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

errors.net
Also called by 2 other listings: Choose All Languages, Browse Better Today

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

Publishers can request a review.

Findings

Every page visit reported to errors.net with persistent user ID

HighunwantedCWE-359Dynamic sandbox

Dynamic analysis captured 18 POSTs from this extension to errors.net in one session across 5+ sites, each carrying the page's full URL and a persistent install ID.

What actually happens

You did this

You navigate to any page in the browser.

The content script is injected on all URLs (*://*/*) and fires on window load.

The extension did this

The extension sends the full page URL and a persistent identifier to errors.net.

The service worker POSTs a JSON body containing your UUID, the page URL (in the errorpage field), navigation timing, and screen geometry to https://errors.net/performance/?license=5kl2IeB97uBryUBcyPfEZ31ZPcv7qIFQoApXHa0O.

Fields sent to errors.net in every POST

  • Persistent user ID
    b6849dd340e74dbd83d211a99980ca96

    A UUID generated once on install and stored permanently, letting errors.net link every report to the same install across sessions.

  • Page URL
    https://en.wikipedia.org/wiki/Test_Page_12345

    The full URL of the page you visited, including path and query string. Sent as the errorpage field in the POST body.

  • Navigation timing
    {domainLookupStart: 12.4, connectStart: 18.1, responseStart: 94.7, domComplete: 1203.2, duration: 1318.5}

    Millisecond-precision breakdown of DNS lookup, TCP connect, server response, DOM load, and page load for the visited page.

  • Screen and window geometry
    {outerHeight: 1080, innerHeight: 937, outerWidth: 1920, innerWidth: 1920, screenTop: 0, screenLeft: 0}

    Outer and inner window dimensions and screen position offsets. Can contribute to browser fingerprinting.

The code that does this

Content script collects data; service worker exfiltrates it

Readable version

performance.js — data collection and message send

performance.js
(function () {  'use strict';  if (document.readyState === 'complete') {    startCollect();  } else {    window.addEventListener('load', startCollect);  }  function startCollect() {    const errorTest = performance.getEntriesByType('navigation')[0].toJSON();    delete errorTest.servererrorTest;    if (errorTest.duration > 0) {      const adjustment = errorTest.fetchStart < 0 ? -errorTest.fetchStart : 0;      const fields = [        'domainLookupStart',        'domainLookupEnd',        'connectStart',        'connectEnd',        'requestStart',        'responseStart',        'responseEnd',        'domComplete',        'domInteractive',        'domContentLoadedEventStart',        'domContentLoadedEventEnd',        'loadEventStart',        'loadEventEnd',        'duration',      ];      fields.forEach((i) => {        errorTest[i] += adjustment;      });      const isFF = navigator.userAgent.indexOf('Firefox') > -1;      const duration = errorTest.duration / 1000;      let precision = duration >= 100 ? 0 : duration >= 10 ? 1 : 2;      if (isFF) {        precision = Math.max(0, precision - 1);      }      const time = duration.toFixed(precision).substring(0, isFF ? 3 : 4);      const dimensions = {        offset: {          x: screenTop + (outerHeight - innerHeight),          y: screenLeft + (outerWidth - innerWidth),        },        details: {          x: screenTop,          y: screenLeft,          oh: outerHeight,          ih: innerHeight,          ow: outerWidth,          iw: innerWidth,        },      };      const promise = chrome.runtime.sendMessage({        time,        errorTest,        dimensions,      });      promise.catch((reason) => console.log(reason));    } else {      setTimeout(startCollect, 100);    }  }})();

worker.js — UUID retrieval and POST to errors.net

worker.js
const apikey = "5kl2IeB97uBryUBcyPfEZ31ZPcv7qIFQoApXHa0O";async function handleEvent(details) {  const { uuid, errorpages } = await chrome.storage.sync.get(['uuid', 'errorpages']);  // ... reads uuid, attaches errorpage = visited URL, POSTs to errors.net  handleErrorResponse(await errorLookup({ uuid, performance: details.errorTest, dimensions: details.dimensions }));}const errorLookup = async details => (await fetch(`https://errors.net/performance/?license=${apikey}`, {  method: 'POST',  headers: { 'Content-Type': 'application/json' },  body: JSON.stringify(details),})).json();

Captured request

POSThttps://errors.net/performance/?license=5kl2IeB97uBryUBcyPfEZ31ZPcv7qIFQoApXHa0O

DA-confirmed: 18 POSTs observed across 5+ distinct hosts in a single browsing session. A planted marker URL was confirmed in the errorpage field during dynamic analysis.

Headers
Content-Type
application/json
Body
{  "uuid": "b6849dd340e74dbd83d211a99980ca96",  "performance": {    "name": "https://en.wikipedia.org/wiki/Test_Page_12345",    "errorpage": "https://en.wikipedia.org/wiki/Test_Page_12345",    "domainLookupStart": 14.2,    "domainLookupEnd": 18.7,    "connectStart": 18.7,    "connectEnd": 89.3,    "requestStart": 89.5,    "responseStart": 201.4,    "responseEnd": 289.6,    "domComplete": 1187.3,    "domInteractive": 943.1,    "domContentLoadedEventStart": 943.2,    "domContentLoadedEventEnd": 943.8,    "loadEventStart": 1187.4,    "loadEventEnd": 1188.1,    "duration": 1188.2,    "error": "UNKNOWN"  },  "dimensions": {    "offset": {      "x": 0,      "y": 143    },    "details": {      "x": 0,      "y": 0,      "oh": 1080,      "ih": 937,      "ow": 1920,      "iw": 1920    }  }}

Destination receiving browsing data

    • errors.net

    Receives full page URLs, persistent UUID, navigation timing, and screen dimensions for every visited host. Controlled by the extension developer.

errors.net controls which URLs the browser opens after every page visit

MediumunwantedCWE-829Dynamic sandbox

Dynamic analysis observed this extension open a tab to a URL chosen by the errors.net server.

What actually happens

You did this

You visit a page the extension has not recently reported.

The extension's loop guard ensures a POST fires on the first visit to each distinct hostname per session.

The extension did this

The browser opens a new tab or window to a URL chosen entirely by the errors.net server.

handleErrorResponse passes the server's JSON response verbatim to chrome.tabs.create (if the response has a notice field) or chrome.windows.create (if it has an alert field), with no URL allowlist or scheme check.

The code that does this

Server response passed verbatim to tab/window creation

Readable version
// worker.js — same code is readable (not obfuscated)// errorLookup returns raw parsed JSON from errors.net.// handleErrorResponse passes that JSON directly://   n.notice -> chrome.tabs.create(n.notice)   // opens a new tab//   n.alert  -> chrome.windows.create(n.alert)  // opens a new window// No URL scheme check, no allowlist, no user confirmation.

Captured request

POSThttps://errors.net/performance/?license=5kl2IeB97uBryUBcyPfEZ31ZPcv7qIFQoApXHa0O

DA confirmed: errors.net returned {notice: {url: 'https://errors.net/error/?...Test_Page_12345...'}} in request #294. The extension immediately opened a new tab to that URL, which loaded errors.net/error/ CSS assets (rows 330-331) and then fired a navigation-timing POST for the newly opened errors.net page (rows 332-333).

Headers
Content-Type
application/json
Body
{  "uuid": "b6849dd340e74dbd83d211a99980ca96",  "performance": {    "name": "https://en.wikipedia.org/wiki/Test_Page_12345",    "errorpage": "https://en.wikipedia.org/wiki/Test_Page_12345",    "error": "UNKNOWN"  },  "dimensions": {    "offset": {      "x": 0,      "y": 143    },    "details": {      "x": 0,      "y": 0,      "oh": 1080,      "ih": 937,      "ow": 1920,      "iw": 1920    }  }}

Server that controls tab destinations

    • errors.net

    Determines which URLs the extension opens in new tabs or windows. The server can direct the browser to any URL by including a notice or alert field in its response.

What it can do

Permissions this extension asks for, as declared in version 4.2. 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

    http://*/*

  • Read and change your data on every secure site you visit

    https://*/*

  • Watch every request your browser makes

    webRequest

  • See every page you navigate to, as you navigate to it

    webNavigation

  • Store data in your browser

    storage

Updated 30 September 2026clgfnfmnfijeennnadfnmfdcemmigaci