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.
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. 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...
How the Hack Worked
- The Injected Links: The hacker's script created millions of fake web addresses like
www.sedssl.org/?o=41723607101460andwww.sedssl.org/product/review/15986057061460. - 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.
- 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...
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 Type | Date Requested | Status |
|---|---|---|---|
https://sedssl.org/?o= | Prefix Removal | Aug 15, 2026 | Temporarily Removed |
https://sedssl.org/product/category | Prefix Removal | Aug 25, 2026 | Temporarily Removed |
https://www.sedssl.org/product/category | Prefix Removal | Aug 25, 2026 | Temporarily Removed |
https://sedssl.org/product/review | Prefix Removal | Aug 25, 2026 | Temporarily Removed |
https://www.sedssl.org/product/review | Prefix Removal | Aug 25, 2026 | Temporarily Removed |
https://sedssl.org/contents/event/kansyasai | Prefix Removal | Aug 31, 2026 | Temporarily Removed |
https://www.sedssl.org/shop/storeSearch/ | Prefix Removal | Sep 01, 2026 | Temporarily 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 lines1
(http.request.uri.query contains "o=") or2
(http.request.uri.path contains "/product/category") or3
(http.request.uri.path contains "wp-") or4
(http.request.uri.path eq "/shop/storeSearch/KeepCriteriaInput.aspx") or5
(http.request.full_uri contains "KeepCriteriaInput.aspx") or6
(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...
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 lines1
/**2
* SEDS Sri Lanka - Ghost Link Cleaner3
* 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...
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:

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

7. Testing in the Terminal: Watching It Work
Before celebrating, I opened the terminal and tested every single attack pattern using
curl:⟨/⟩BASH
17 lines1
# Test 1: Fake number link2
$ curl -IL "https://www.sedssl.org/?o=41723607101460"3
HTTP/2 410 Gone4
x-robots-tag: noindex, nofollow, noarchive5
6
# Test 2: Fake product review link7
$ curl -IL "https://www.sedssl.org/product/review/15986057061460"8
HTTP/2 410 Gone9
10
# Test 3: Fake Japanese event link11
$ curl -IL "https://www.sedssl.org/contents/event/kansyasai/31055966010460"12
HTTP/2 410 Gone13
14
# Test 4: Real SEDS SL Homepage15
$ curl -I "https://www.sedssl.org/"16
HTTP/2 200 OK17
server: VercelEvery spam link was instantly wiped out with
Every real page loaded instantly 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...
Googlebot is now rapidly clearing out the old ghost links every time it crawls our domain.
3 Lessons Every Webmaster Should Know
- 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.
- 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.
- 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.

