Malicious Service Workers and Push Notification Spam
By Glenn Lyvers · Updated · 4 min read
A customer emails to say they are getting pop-up adverts on their computer, and they are certain the alerts mention your site. They have not visited you in a week. Nothing on your server is running on their machine — but something you served them is, and that is what makes this infection unusually stubborn to clean up.
What a service worker is
A service worker is a script a website can register in a visitor's browser. Once registered, it lives outside any particular tab, persists after the visitor leaves, and can wake up to do work — the legitimate uses are offline caching, background sync and genuine push notifications for things like messaging apps.
The critical property is persistence. A normal script stops when the page closes. A service worker stays registered on that person's browser until they clear it or it is unregistered, and it can keep receiving push messages from whoever controls it. Compromise the script your site registers and you have a durable foothold in the browsers of everybody who visited during the infected window.
How attackers abuse it
Injected code on your pages registers a service worker from a path on your own domain, then prompts visitors to allow notifications — often behind a dark pattern, like a fake age check, a fake captcha or a fake video player that claims a click is needed to continue. Visitors who accept are subscribed to a push channel the attacker controls.
From that point the operator can deliver notifications directly to the desktop or phone, which look like system alerts rather than website content. They are typically scam offers, fake virus warnings or adult content, and they arrive with your domain attached because that is where the subscription came from. That is why the complaints reach you long after the person stopped visiting.
Finding it on your site
Look for the registration and the worker file. In your rendered page source, search for service worker registration calls and note the path they point at. Then look for that file on disk, commonly in the web root under a plausible name such as a short script file that looks like it belongs.
Your browser's developer tools will show you what is registered when you visit your own site: the application panel lists active service workers, their source file and their scope. Anything registered that you did not deliberately build — particularly on a site with no offline features and no legitimate notification product — should not be there. Also check whether a caching or progressive-web-app plugin is responsible, since those register workers legitimately and you want to avoid deleting a real feature.
Removing it from your site
Delete the malicious worker file and remove the registration code from wherever it is being injected — theme files, the database, or a plugin's settings. Then treat the site as compromised in the ordinary way, because injected registration code means someone had write access. My guide on injected JavaScript covers tracing that back to its source.
One important detail: serving a 404 for the deleted worker file is not enough on its own to clear existing registrations quickly. The cleanest approach is to replace the file with a minimal worker that unregisters itself, so browsers that still hold the old one fetch the replacement and tear the registration down. That turns a passive fix into an active one.
The part you cannot fix from your server
Here is the uncomfortable truth about this infection: cleaning your site stops new victims, but it does not automatically clean the people already subscribed. Their browser holds a registration and a notification permission, both granted to your domain, and both persist independently of your server.
So this needs communication as well as cleanup. Publish a short notice explaining what happened and how to fix it — revoke notification permission for your domain in browser settings, and clear site data for your domain, which removes the registration. It is a small amount of writing that saves your reputation with the people most affected, and my guide on telling customers after a hack covers how to pitch it.
Preventing it next time
The registration only happened because someone could inject code into your pages, so the prevention is the ordinary prevention: update everything, remove unused plugins, put two-factor authentication on administrator accounts, and close whatever route let them write to your site. My hardening guide covers the practical list.
It is also worth periodically checking your own site in developer tools to see what it registers, since this is one of the few infections that leaves a visible, checkable artefact. If notifications are showing up for visitors and you cannot find the source, that is a reasonable point to hand it over — my malware removal service covers the full sweep including the database side.
Common questions
Why do visitors still get spam after I cleaned my site?
Because the service worker and the notification permission live in their browser, not on your server. Cleaning your files stops new registrations but does nothing about existing ones. Those clear when the visitor revokes the permission and clears site data for your domain, or when a replacement worker unregisters itself.
How do I check what service workers my site registers?
Open your site in Chrome or Firefox, open developer tools, and look at the application or storage panel. Registered service workers are listed there with their source file and scope. If you see one you did not build and you do not run a caching or progressive-web-app plugin, that is your problem.
Can a service worker steal data?
It sits between the browser and the network for pages in its scope, so a malicious one has significant capability — it can see and potentially alter requests within its scope. Most of these campaigns are after notification-spam revenue rather than data, but you should assume capability rather than trust intent.
Is deleting the worker file enough?
It stops the file being served, but browsers that already registered it may hold it for a while. The more effective move is to replace it with a minimal worker whose only job is to unregister itself, so existing installations actively tear themselves down when they next check for an update.
Could a legitimate plugin be registering this?
Yes, and it is worth checking before you delete anything. Caching plugins, progressive-web-app plugins and genuine push-notification services all register service workers as part of normal operation. Confirm what is installed and what it is meant to do, so you remove the malicious registration rather than breaking a feature you rely on.
More than malware
Most people meet me in an emergency. It isn’t all I do.
I’ve been building and repairing systems since 1995. Whatever brought you here, there’s a good chance I can help with the rest of it too — and you’ll be dealing with the same person either way.
Hacked, but not WordPress?
Joomla, Drupal, Magento, Shopify, PrestaShop, Laravel, Node, IIS and plain HTML — cleaned the same way, priced the same way.
Take a look →Custom builds & AI systems
Plugins, custom applications, website chatbots and automation — built to do exactly what you need, maintained by the person who wrote them.
Take a look →Servers, speed, SEO & accessibility
Migrations, faster load times, technical SEO and accessibility fixes. Measured improvements, with the numbers to show you.
Take a look →Better web hosting
Fast, secure hosting with SSL and backups included at no extra charge. Clear pricing, no long-term contracts, no surprises.
Take a look →Classes & free tools
Rather learn to handle it yourself? I teach this, and I give away the tools I built for my own cleanups.
Take a look →Something else broken?
Half my work is untangling what someone else started, gave up on, or broke. Describe it in plain words and I’ll tell you honestly.
Take a look →Tell me what’s wrong. I’ll tell you what it takes.
No queue, no call centre, no sales pitch — one person who answers, quotes honestly, and does the work.