Login
ChallengesLearn
Scoreboard
Teams
Profile

Preferences

Truesapiens

LearnCross Site ScriptingXSS Case Studies
Cross Site Scripting·Lesson 11 of 12

XSS Case Studies

Samy (MySpace 2005) — the first XSS worm. Twitter onmouseover (2010). eBay DOM XSS (2014). British Airways/Magecart (2018). The payloads, the root causes, the post-mortems.

Intermediate18 min
XSSHistoryBreaches
Loading lesson…
PreviousXSS Detection & AuditingNextXSS Review & Practice

© 2026 Truesapiens.

Terms of ServicePrivacy PolicyCookie Policy

From the first self-replicating XSS worm on MySpace to the Magecart supply-chain attack on British Airways, these case studies show how the same class of bug — untrusted data reaching a script execution context — has caused billions of dollars in damage across two decades.

What you'll be able to do
  • Describe the Samy worm payload and how it bypassed MySpace filters.
  • Explain the Twitter onmouseover worm and why 140 characters was enough.
  • Identify the DOM source and sink in the 2014 eBay XSS.
  • Trace the Magecart supply-chain attack from third-party JS to payment form.
Key terms
XSS worm
A self-propagating XSS payload that replicates itself across user profiles without any server-side exploit. The Samy worm on MySpace was the first.
Supply-chain XSS
An XSS vulnerability introduced through a third-party script or library loaded by the application. The application inherits the security posture of every script it includes.
Polyglot payload
A payload that works across multiple contexts — for example, a string that is both valid CSS and valid JavaScript — used to bypass context-specific filters.
Magecart
A group of threat actors who specialise in injecting card-skimmer scripts into e-commerce checkout pages, often via DOM XSS in third-party libraries.
What is it?

Four attacks that changed the web

The Samy worm (MySpace 2005) was the first XSS worm. Samy Kamkar found that MySpace filtered <script>, <body>, and onclick, but allowed onmouseover and CSSbackground: url(). He crafted a polyglot payload that combined CSS background: url(javascript:…) with onmouseover — when a user hovered over his profile, the payload added them as a friend and copied itself to their profile. Within 20 hours, over one million MySpace users were infected.

The Twitter onmouseover worm (2010) proved that even a 140-character tweet could carry an XSS payload. A user posted @<img src="x" onerror="…">. Twitter's text parser treated the tweet as plain text but failed to escape the content inside the <img> tag when rendering user profiles. Hovering over the tweet triggered the payload, retweeting the worm to the user's followers.

XSS worm propagation
Mini Map
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Try it

Case study timeline

Click through each case study to see the payload, the root cause, the vulnerable code, and the fix. Each entry includes a side-by-side comparison of the vulnerability and its remediation.

prodcase-explorer.io/timeline
case-explorer
Timeline
MySpace — Samy worm2005

First XSS worm. 1 million infected in 20 hours.

Payload
<div onmouseover="eval(fetch('/profile').then(x=>x.text()).then(t=>{/* copy payload */}))" style="background:url(javascript:alert(1))">hover</div>
Root cause

CSS background: url(javascript:…) bypassed MySpace filter. onmouseover was not blocked.

The fix

Switch from tag blocklist to context-aware HTML escaping. Use safe CSS property whitelist.

Vulnerable
// MySpace blocked <script>, <body>, onclick
// but missed CSS javascript: URLs and onmouseover
sanitizer.blockTags(["script", "body"]);
sanitizer.blockAttrs(["onclick"]);
// onmouseover + CSS syntax passed through
Patched
// Context-aware sanitisation
import { sanitize } from "isomorphic-dompurify";
const clean = sanitize(input, {
  ALLOWED_TAGS: ["b", "i", "u", "a"],
  ALLOWED_ATTR: ["href"],
});
// CSS properties validated by whitelist
Real-world relevance

eBay DOM XSS 2014 — the sink was hiding in plain sight

In 2014, security researcher Jann Horn discovered a DOM-based XSS on eBay's item listing page. The vulnerable JavaScript read the item category from the URL hash and wrote it into the page via innerHTML. The category value was not validated or escaped because it was assumed to come from eBay's own server — but the server never received the hash fragment. An attacker could craft a link like /item/123#<script>…</script>and send it via eBay's own messaging system.

The eBay case illustrates a recurring pattern: developers assume a value is safe because it originates from a trusted source, but the value reaches the browser through an attacker-accessible channel. In this case, the category parameter in the hash fragment was never meant to be user-controlled, but the application provided no server-side validation to enforce that assumption.

Mitigation

Lessons from two decades of XSS

Each case study reinforces the same principle: context-aware escaping must happen at the output layer, not the input layer. MySpace filtered specific tags but the attacker found a polyglot. Twitter trusted the text parser but the browser parsed the event handler. eBay trusted the URL hash because the server did not control it. The fix is always the same — escape for the correct context at the point where the value enters the DOM.

javascriptsafe
// VULNERABLE — MySpace-style filter approach
const blocked = ['script', 'body', 'onclick'];
function isSafe(input: string): boolean {
  return blocked.every((b) => !input.includes(b));
}
// Bypassed with onmouseover + CSS javascript: url

// VULNERABLE — eBay DOM XSS
const category = location.hash.slice(1);
document.getElementById('breadcrumb')!.innerHTML = category;

// SAFE — context-aware output escaping
const category = location.hash.slice(1);
document.getElementById('breadcrumb')!.textContent = category;
// textContent disables HTML parsing — no script execution

// SAFE — validate and sanitise at the sink
function safeSetHtml(el: HTMLElement, value: string) {
  el.textContent = value; // never innerHTML
}
Further reading
  • Samy Kamkar — Technical MySpace worm writeup(Samy Kamkar)
  • Twitter onmouseover worm analysis(Sophos Naked Security)
  • eBay DOM XSS disclosure (Jann Horn)(Full Disclosure)
  • British Airways ICO fine — Magecart analysis(ICO)
Key takeaways

What to remember

  • The Samy worm (2005) proved that XSS can self-propagate — no server exploit needed.
  • Filter-based defences are fragile; a polyglot payload bypasses tag blocklists.
  • The Twitter worm (2010) showed that even short text fields can carry XSS when parsing and rendering disagree.
  • eBay's DOM XSS (2014) is the textbook example of a hash-fragment source reaching an innerHTML sink.
  • British Airways / Magecart (2018) demonstrates supply-chain XSS: the vulnerability was in a third-party script, not first-party code.

Knowledge check

0/3 answered · 0 correct
  1. 1.How did the Samy worm bypass MySpace filter that blocked <script>, <body>, and onclick?

  2. 2.What was the root cause of the eBay 2014 DOM XSS?

  3. 3.What is the key difference between the Samy worm and the Magecart/BA attack?