Was looking for alternatives to AdSense, and saw an ad for Monetag. Look at their js file they want you to upload the server, then peeped the import. Import is minified js so I had claude take a look at it. The first tool I used identified what it thought was a base64 encoded blob which is a red flag.
This is a pretty scummy way, with those stupid popups, to handle business. The obsfucation, along with what it actually does, is a larger red flag for me than some clown giving away puppies in a van.
About the “base64 blob”
There isn’t one. What looks like a blob is the big string table at the end of minified.js (about 1,135 entries). It isn’t base64. Each letter is just shifted 12 places in the alphabet (a ROT-12 cipher), which is why it looks like gibberish (tffbe:// is https://). Every K.xx in the code looks up an entry in that table. In the readable file, all of them are replaced with the plain-text values.
The only real base64 in the file:
- Line 1015
urlBase64ToUint8Array: converts the push-notification server key, a standard step for web push.
- Line 321
btoa(e): base64-encodes a URL into a request header called token. More on this below.
What the script is
It’s Monetag’s push-notification service worker, version 3.1.647 (line 1346). Websites that run Monetag ads install it. It stays in the visitor’s browser after they leave the site, receives push messages, shows ad notifications and reports stats back. The servers it talks to:
Findings, most important first
- The server can redirect the browser anywhere, and the script quietly reinstalls itself (lines 1531–1548, 1441). When a notification is clicked, the script sends the browser to a fake page at
<site>/fdsdrtytrertyuygtfghjhgfrtywertyuiytrertyuytre. The script answers that address itself, so the request never reaches the site. The page re-registers a service worker from a scriptURL taken from the URL, then redirects to next without checking where it points. For browsers that already have this worker, that address on the site is an open redirect (it will send visitors to any URL in the link). Browsers only allow a service worker from the site’s own domain, so scriptURL can’t load a worker from another site.
- It skips installing when Google’s Lighthouse auditing tool is running (line 2529, checks for
Chrome-Lighthouse). This keeps it out of automated site audits. It’s a sign of deliberate evasion.
- It rewrites built-in notification functions (lines 79–124). It replaces
Notification.prototype.close and ServiceWorkerRegistration.prototype.showNotification across the whole worker to track when notifications are shown and closed.
- The server can change it remotely (line 1861 and the
handleFeatureFlags function). A push message with sw_config can swap out the event, ping and fallback servers, so its behaviour can change without the file changing.
- It collects device details (lines 369–379 and 1577–1615). It reads high-entropy browser hints (device model, OS version, CPU architecture and bitness, full browser version list) plus
WGL (likely a WebGL graphics-card value), a long-lived user key, an install ID, and counts of notifications shown and dismissed. It sends these with ad requests.
- It has a backup route that hides its traffic (lines 309–323, 1033). If a normal request fails, it retries through domains stored in a local
domains database. It requests random-looking paths, sends cookies, and puts the real URL in base64 in a token header. This is built to get around ad blockers. In this file nothing ever adds a domain (addDomain is defined but never called), so it only does anything if another script on the same site fills that list.
- Minor issues:
- Spammy notifications: the fallback ad is “Personal Offer for You. / We found 1 offer that might interest you” with
requireInteraction: true (line 1347), so it stays on screen until clicked. Repeated and “bubbled” notifications (lines 195, 574) keep re-showing old ones.
- Unchecked messages: the message handler (line 2022) accepts
subscribe/ping commands without checking who sent them. That’s normal for a service worker, but worth knowing.
- Bug: on a fatal error, the fake page sends its error report to its own URL instead of the logging server.