When a Cloudflare Worker clones your website: how we spotted it and shut it down

Michael Walsh
By Michael WalshPublished

A single Cloudflare security rule blocked a live clone of one of our clients' websites, and it should work for any site that can sit behind Cloudflare.

A single Cloudflare security rule blocked a live clone of one of our clients’ websites, and it should work for any site that can sit behind Cloudflare.

The clone was running on a lookalike domain (think yourbrand.live instead of yourbrand.com). It wasn’t a static copy. Every page was fetched from the real site at the moment a visitor asked for it, so the clone always showed current products, prices and stock. Anyone landing there would reasonably believe they were on the genuine site.

This post covers how these clones work, why the usual JavaScript fix doesn’t stop them, how to confirm what you’re dealing with, and the Cloudflare rule that shut it down.

How the clone works

The clone is a Cloudflare Worker acting as a reverse proxy. A Worker is a small piece of code that runs on Cloudflare’s network, and it costs nothing to set up. Each request to the lookalike domain goes through four steps:

  1. A visitor requests a page on the lookalike domain.
  2. The Worker fetches the same page from the genuine site.
  3. The Worker rewrites the HTML, swapping the real domain for its own so links, forms and assets keep visitors on the clone.
  4. The rewritten page is sent back to the visitor.

The more capable versions also inject their own JavaScript. In our case, that script intercepted navigation in the browser: any attempt to send the visitor to another domain was quietly rewritten into a URL on the clone.

We can’t say for certain what the operator was after. Setups like this are commonly used for phishing, harvesting logins or payment details, or hijacking search traffic. The same domain had previously been used to clone a different business, so it wasn’t a one-off.

Why a JavaScript hostname check isn’t enough

The common defence is a script in the page that checks the hostname and redirects anywhere unexpected back to the real site. Our client already had one:

if (!['yourbrand.com', 'www.yourbrand.com'].includes(window.location.hostname)) {
window.location.href = 'https://yourbrand.com' + window.location.pathname;
}

It did nothing on the clone, for two reasons.

The proxy rewrites the script. The Worker replaces every occurrence of the real domain in the page, and it can’t tell a link from a line of code. By the time the script reached the visitor’s browser, the allow-list contained the clone’s domain, so the check passed. The redirect target had been rewritten too.

The proxy intercepts navigation. We obfuscated the domain names so a find-and-replace couldn’t match them, and the check started firing. But the injected script caught the redirect and turned it into another page on the clone. Because our redirect carried the current path and query string across, each loop wrapped the previous URL inside a new one. The address bar grew until the browser gave up.

If you do use a script, don’t redirect. On an unexpected hostname, stop the page loading and replace it with a plain warning that tells visitors to type the real address themselves. A link would just be intercepted. Even then, the operator can strip inline scripts in a few lines of code, so treat it as a fallback rather than the fix.

Confirming it’s a Cloudflare Worker

The fix below only works against Workers, so check first. Request the clone’s headers:

curl -sI https://yourbrand.live/

Three things in the response point to a Worker proxy:

  • server: cloudflare and a cf-ray header show the clone is served through Cloudflare.
  • Your own platform’s headers and cookies (in our case, the e-commerce platform’s session cookies and the live theme ID) show your real response is being passed straight through.
  • The network your origin saw the request come from. Some platforms report this in a header. Ours showed the request arriving from Cloudflare’s own network rather than a hosting provider, which is what you’d expect from an outbound Worker request.

If the clone runs on an ordinary server behind Cloudflare instead, the rule below won’t catch it, and you’ll be relying on abuse reports to the host.

The fix: one Cloudflare security rule

When a Worker fetches a site that’s also proxied through Cloudflare, Cloudflare tags the request with the zone the Worker belongs to. That value is exposed to your security rules as cf.worker.upstream_zone, and the Worker can’t remove it. So if your site is behind Cloudflare, you can block every request that came from someone else’s Worker.

If you don’t use Workers on your own site, the simplest rule blocks all of them:

(cf.worker.upstream_zone ne "")

If you do, exclude your own zone:

(cf.worker.upstream_zone ne "" and cf.worker.upstream_zone ne "yourbrand.com")

Either version is better than matching the clone’s domain by name. Operators move to new domains, and a rule naming one domain stops working the day they do. This rule works for any domain they move to, as long as they stay on Cloudflare Workers.

To add it:

  1. In the Cloudflare dashboard, open your site’s zone.
  2. Go to Security, then Security rules (WAF → Custom rules on older dashboards). Note that the Rules section is the wrong place; it covers redirects and caching.
  3. Click Create rule and choose a custom rule.
  4. Give it a name, such as “Block third-party Worker proxies”.
  5. Click Edit expression and paste in the rule. The field may not appear in the visual builder’s dropdown.
  6. Set the action to Block and click Deploy.

Then test it:

curl -sI https://yourbrand.live/

You should get a 403, and the blocked requests appear under Security → Events, showing which zone they came from. The rule works on Cloudflare’s Free plan.

One thing to watch: the rule also blocks legitimate services that happen to run on Workers and fetch your pages, such as some feed generators, link-preview tools or monitors. It’s uncommon, but check Security Events now and then for the first week or so.

If your site is on Shopify or another hosted platform

You can still use the rule. Our client’s store was on Shopify, which doesn’t let you add firewall rules of your own. Shopify already runs on Cloudflare, though, and Cloudflare supports putting your own zone in front of it. Cloudflare calls this Orange-to-Orange (O2O). Your zone’s rules run first, then the request passes on to Shopify. It works on any Cloudflare plan, including Free, and Cloudflare has similar guides for other platforms such as BigCommerce and Webflow.

To set it up:

  1. Add the domain to Cloudflare and import the existing DNS records. The domain registration can stay where it is.
  2. Compare the imported records against your old DNS provider’s. Check that MX, SPF, DKIM, DMARC and any verification records came across, and delete any of the old provider’s nameserver records that were imported at the root.
  3. Point the root domain and www at shops.myshopify.com with CNAME records set to Proxied. Cloudflare flattens the CNAME at the root, so this is allowed. Cloudflare shows a Shopify icon beside records it recognises as O2O.
  4. Leave everything else, including mail and third-party service records, as DNS only.
  5. Add the security rule before you switch nameservers, so it’s active as soon as traffic arrives.
  6. Change the nameservers at your registrar to the two Cloudflare gives you. Keep the old DNS zone for a few days until the change has fully propagated.

A few Shopify-specific points:

  • Leave Always Use HTTPS off. It interferes with the path Shopify uses to renew its SSL certificate. Shopify redirects to HTTPS itself anyway.
  • Expect a warning in the Shopify admin that the domain is behind a Cloudflare proxy. With O2O, it’s safe to ignore as long as the store and checkout work.
  • Your own Workers can’t touch checkout. Cloudflare disables them on Shopify’s /checkout path, but security rules still apply there.

We also looked at putting AWS CloudFront and AWS WAF in front of Shopify instead. It can be made to work, but Shopify doesn’t support it, and it complicates domain verification, SSL and checkout fraud checks. O2O is the cleaner route.

Backing it up

The rule stops the clone from loading your pages, but the domain and the Worker still exist. Three further steps close the gaps.

Report it to Cloudflare as phishing at abuse.cloudflare.com. Because the Worker runs on Cloudflare, Cloudflare is effectively the host and can take it down entirely. Include the cf-ray ID and timestamp from your curl output, which lets them trace the exact request. When the form asks whether to forward your report to the website owner, untick the option to include your contact details. The owner is the attacker.

Report it to Google Safe Browsing. Browsers then show visitors a red warning page, which protects people faster than waiting for the clone to drop out of search results.

Keep a warning-page script in your site. If the operator moves the clone to an ordinary server, the rule no longer applies. As described above, the script should stop the page and show a warning rather than redirect, and should hide your domain names from find-and-replace, for example by storing them reversed and flipping them at runtime.

Checklist

If you find a live clone of your site:

  • Run curl -sI against the clone to confirm it’s served through Cloudflare
  • Put your site behind Cloudflare if it isn’t already, using O2O for hosted platforms
  • Add a security rule blocking cf.worker.upstream_zone ne ""
  • Test that the clone now returns a 403
  • Report it to Cloudflare as phishing and to Google Safe Browsing
  • Add or update a warning-page script as a fallback
  • Check Security Events for a week or so for anything legitimate being blocked

If you’ve found a clone of your own site and would like help, get in touch.

We use cookies to make this website work, to understand how it's used, and to measure our advertising. Find out more about cookies.

Cookie preferences

make an enquiry

Quick form · 3 steps · 1 min

How can we help?

Pick the closest match. We reply within one business day.

I am looking for

Website

New marketing website, microsite or redesign

E-commerce

Shopify store, new or rebuilt

Web application From £10,000 + VAT

Bespoke software and internal tools

AI implementation From £10,000 + VAT

Practical AI in your existing systems

Data visualisation From £10,000 + VAT

Dashboards and data pipelines

Migrations, hosting & support

Website migrations, web hosting and ongoing support

Something else / not sure yet

Let's talk it through

Prefer to talk?Book a call

Step 1 of 3

We'll be in touch within one business day to discuss your project. In the meantime, feel free to drop us a line at hello@enovate.co.uk if anything else comes up.

book directly

Book a discovery call with Michael

Michael Walsh, Founder & Managing Director. Pick a time that suits you, add your name and email, and the calendar invitation is yours.

Loading available times…

You can still book through the full calendar, orsend us a message.

Times shown in . The calendar invitation lands in your inbox the moment you confirm.

Booking is handled by Calendly; see our privacy policy.

You're booked in

(). The calendar invitation is on its way to .

RescheduleCancel