How I Purged 1.3 Million Ghost Pages from www.sedssl.org

A Webmaster's 60-Day War on SEO Spam, Crashed Servers, and Google's Index

Author: Thawshi Srikanth
Role: Webmaster, SEDS Sri Lanka
Appointed: July 6, 2026
Incident Discovered & Escalated: July 20, 2026
Active Battle: July 20 to September 14, 2026
The Core Challenge: 500,000 spam pages already indexed on Google, and 800,000 more waiting in line.

Prologue: Welcome to Day One, Everything Is Broken

On July 6, 2026, I was appointed as the Webmaster for SEDS Sri Lanka (Students for the Exploration and Development of Space).
I thought my first month would be simple: fix a few buttons, speed up page loads, and publish updates about our rocketry and astronomy projects like SaveDino.
Instead, when I opened www.sedssl.org in mid-July, the entire website was dead. The server had crashed and refused to load.
I opened Google Search Console to see what was going on. What I saw felt unreal:
Google had discovered over 1.3 million URLs under our domain.
Even worse: over 500,000 of these spam pages were already live and indexed on Google Search.
If you searched for our non-profit space organization, you didn't see rockets or stars. You saw fake Japanese discount stores, fake shoe reviews, and spam links that redirected visitors to shady online shops.
On July 20, 2026, I delivered the emergency incident briefing to our leadership team:
"Our site is down, our old server was hacked, and we have 500,000 spam pages live on Google with 800,000 more in the pipeline."
From that exact day, the recovery war began.
1.3 Million Ghost URLs Breakdown
Loading diagram...
1.3 Million Ghost URLs Breakdown

1. What Happened? (The Forensic Timeline)

Before fixing the problem, I had to understand what went wrong and when.
By analyzing Google Search Console crawl history and DNS logs, I mapped out the incident lifecycle:
SEDS SL Incident & Recovery Timeline
Loading diagram...
SEDS SL Incident & Recovery Timeline

How the Hack Worked

  1. The Injected Links: The hacker's script created millions of fake web addresses like www.sedssl.org/?o=41723607101460 and www.sedssl.org/product/review/15986057061460.
  2. The Cloaking Trick:
    • When Googlebot visited, the server returned keyword-stuffed HTML so Google would rank it.
    • When a real human clicked from Google, the server immediately executed a redirect to external spam shops.
  3. The Spider Trap: Each fake page contained links to 50 more fake pages, trapping Googlebot in an endless indexing loop that indexed over 500,000 pages in weeks.

2. The Battle Plan: Two Big Jobs

Remediation & Cleanup Strategy
Loading diagram...
Remediation & Cleanup Strategy

3. Step 1: Put Up the Shield (Late July - August)

We couldn't rebuild the entire site in a single afternoon. I needed immediate moves to protect our students and sponsors from seeing spam.

Move 1: Google Search Console Prefix Removals (Aug 15 - Sep 01)

I used Google Search Console's URL Removals tool to execute bulk prefix removals, knocking out entire clusters of malicious ghost URLs from Google's search results all at once:
URL Pattern (Starts with)Removal TypeDate RequestedStatus
https://sedssl.org/?o=Prefix RemovalAug 15, 2026Temporarily Removed
https://sedssl.org/product/categoryPrefix RemovalAug 25, 2026Temporarily Removed
https://www.sedssl.org/product/categoryPrefix RemovalAug 25, 2026Temporarily Removed
https://sedssl.org/product/reviewPrefix RemovalAug 25, 2026Temporarily Removed
https://www.sedssl.org/product/reviewPrefix RemovalAug 25, 2026Temporarily Removed
https://sedssl.org/contents/event/kansyasaiPrefix RemovalAug 31, 2026Temporarily Removed
https://www.sedssl.org/shop/storeSearch/Prefix RemovalSep 01, 2026Temporarily Removed
Note: The GSC Removals tool hides matching links from search results for about 6 months. It acted as an emergency ballistic shield to protect human searchers while we engineered the permanent edge infrastructure.

Move 2: The Emergency Firewall (Cloudflare WAF)

Google's crawlers were hitting our broken server thousands of times a minute. I configured a Cloudflare WAF rule to immediately drop spam patterns:
⟨/⟩TEXT
6 lines
1
(http.request.uri.query contains "o=") or
2
(http.request.uri.path contains "/product/category") or
3
(http.request.uri.path contains "wp-") or
4
(http.request.uri.path eq "/shop/storeSearch/KeepCriteriaInput.aspx") or
5
(http.request.full_uri contains "KeepCriteriaInput.aspx") or
6
(http.request.full_uri contains "index.php")
This stopped our network from drowning. But it brought up the next crucial challenge: How do we make Google delete all 500,000 indexed pages permanently?

4. The Magic Status Code: Why 410 Beats 403 & 404

When Google visits a web page, the server responds with an HTTP status code number. Picking the wrong number can delay recovery by months:
HTTP Status Code Comparison
Loading diagram...
HTTP Status Code Comparison
Standard Cloudflare firewall actions cannot send custom status codes like 410 Gone. To do that, I wrote a small JavaScript program running directly on Cloudflare's edge network: a Cloudflare Worker.

5. Building the Trap: Cloudflare Worker

I deployed a Cloudflare Worker across *sedssl.org/*.
Whenever any visitor or Google bot requests a URL, this code checks the path in under 2 milliseconds. If it matches a spam pattern, it instantly replies with HTTP 410 Gone.
⟨/⟩JAVASCRIPT
44 lines
1
/**
2
 * SEDS Sri Lanka - Ghost Link Cleaner
3
 * Catches 1.3M spam URLs and tells Google they are GONE forever.
4
 */
5
export default {
6
  async fetch(request) {
7
    const url = new URL(request.url);
8
    const { pathname, searchParams } = url;
9

10
    // 1. Check for spam numbers like ?o=123456
11
    const oValue = searchParams.get("o");
12
    const isSpamQuery = oValue !== null && /^\d{6,}$/.test(oValue);
13

14
    // 2. Check for fake store categories and Japanese event pages
15
    const spamPathRegex =
16
      /^\/(product\/(category|review)|contents\/event\/[^/]+)\/\d{6,}/;
17
    const isSpamPath =
18
      spamPathRegex.test(pathname) ||
19
      pathname === "/shop/storeSearch/KeepCriteriaInput.aspx";
20

21
    // 3. Check for old hacker scripts & backdoors
22
    const fullUri = pathname + url.search;
23
    const isSpamFile =
24
      fullUri.includes("KeepCriteriaInput.aspx") ||
25
      fullUri.includes("index.php") ||
26
      pathname.startsWith("/wp-");
27

28
    // If it's spam, kill it with 410 Gone
29
    if (isSpamQuery || isSpamPath || isSpamFile) {
30
      return new Response("HTTP 410 Gone: This page has been permanently deleted.", {
31
        status: 410,
32
        statusText: "Gone",
33
        headers: {
34
          "Content-Type": "text/plain; charset=utf-8",
35
          "X-Robots-Tag": "noindex, nofollow, noarchive",
36
          "Cache-Control": "public, max-age=31536000, immutable",
37
        },
38
      });
39
    }
40

41
    // If it's a real page, let the visitor through!
42
    return fetch(request);
43
  },
44
};

Safety First: Fail Open

The Worker is configured with Fail Open. If the worker ever encounters an unexpected error, it passes the request to the main website rather than blocking real visitors. Real students and space enthusiasts were never interrupted.

6. Throwing Away the Old Server: Rebuilding on Next.js

Fixing the links was only half the job. I never wanted our server to get hacked again.
We decommissioned the old shared hosting completely. I rebuilt SEDS Sri Lanka using Next.js and deployed it to Vercel:
  • No PHP files or old CMS backdoors: Attackers have no writable files or SQL injection points.
  • Hosted on Vercel's global network: Fast, stable, and immune to server crashes.
  • Protected by Cloudflare: Free SSL, DDoS protection, and our custom Cloudflare Worker running at the edge.
Cloudflare Edge Worker Architecture Flow
Loading diagram...
Cloudflare Edge Worker Architecture Flow

Before & After: The Transformation

Here is the contrast between the old compromised setup and the newly rebuilt platform:

Before: The Compromised Legacy Site

The old shared-hosting site was plagued by vulnerability backdoors, spam injection vectors, and unreliable uptime:
Before: The Legacy Compromised Site
Before: The Legacy Compromised Site

After: The Rebuilt Modern Portal

The clean Next.js portal deployed on Vercel: modern, static, fast, and completely immune to PHP injection exploits:
After: Modern Rebuilt SEDS Sri Lanka Portal on Next.js
After: Modern Rebuilt SEDS Sri Lanka Portal on Next.js

7. Testing in the Terminal: Watching It Work

Before celebrating, I opened the terminal and tested every single attack pattern using curl:
⟨/⟩BASH
17 lines
1
# Test 1: Fake number link
2
$ curl -IL "https://www.sedssl.org/?o=41723607101460"
3
HTTP/2 410 Gone
4
x-robots-tag: noindex, nofollow, noarchive
5

6
# Test 2: Fake product review link
7
$ curl -IL "https://www.sedssl.org/product/review/15986057061460"
8
HTTP/2 410 Gone
9

10
# Test 3: Fake Japanese event link
11
$ curl -IL "https://www.sedssl.org/contents/event/kansyasai/31055966010460"
12
HTTP/2 410 Gone
13

14
# Test 4: Real SEDS SL Homepage
15
$ curl -I "https://www.sedssl.org/"
16
HTTP/2 200 OK
17
server: Vercel
Every spam link was instantly wiped out with 410 Gone.
Every real page loaded instantly with 200 OK.

8. The Victory: September 14, 2026

After nearly two months of focused engineering from July 20 to September 14, we ran the official "Validate Fix" inside Google Search Console:
Search Console Fix Validation Dashboard
Loading diagram...
Search Console Fix Validation Dashboard
Googlebot is now rapidly clearing out the old ghost links every time it crawls our domain.

3 Lessons Every Webmaster Should Know

  1. Check Search Console on Day One: When taking over any website, don't just look at the home page. Check Google Search Console immediately to see what Google is actually indexing.
  2. Cheap Hosting is Expensive: Unmanaged cheap hosts with old software are easy targets for hackers. A clean modern stack (Next.js + Cloudflare + Vercel) saves you weeks of headaches.
  3. Use 410 Gone for Spam Cleanup: Don't just throw up a 404 or 403. Tell Google clearly that the pages were permanently deleted with an HTTP 410 Gone header so they disappear from search results fast.
It took 8 weeks of patience, code, and caffeine, but the 1.3 million ghost pages are history.
SEDS Sri Lanka is back where it belongs: focused on exploring space.