Quick answer
XS-Leaks are side channels that let you read binary or small information about a victim logged into another origin — without needing XSS, without directly circumventing SOP. They rely on differences observable from a page that only embeds cross-origin content: load times, parse errors, number of frames, fired events. Useful to detect whether the victim is logged in, whether they're an admin, whether they have a certain role, or to leak IDs one bit at a time.
The threat model
The attacker:
- Hosts
attacker.com. - The victim visits attacker.com (phishing, ads, click-through).
- The attacker embeds / fetches
target.comcross-origin. - The attacker observes browser side channels to infer data.
Modern mitigations: COOP, COEP, CORP, SameSite=Lax by default. But many endpoints are still leakable because the mitigation applies to top-level pages, not the universe of subresources.
Channel 1 — Timing attacks with performance.now()
The most universal. It measures how long a cross-origin resource takes to load. Differences of 20-100ms are usually observable.
Basic setup
async function timeFetch(url) {
const start = performance.now();
await fetch(url, { mode: 'no-cors', credentials: 'include' });
return performance.now() - start;
}
const tLogged = await timeFetch('https://target.com/api/me');
const tSomething = await timeFetch('https://target.com/api/admin-only');
// Si tSomething < tLogged significativamente, admin-only retornó rápido (403)
// Si son similares, retornó datos (admin)
Classic endpoints leakable by timing
| Endpoint | Observable difference |
|---|---|
| Search with a term that exists vs one that doesn't | SQL query time |
/admin/dashboard vs /admin/non-existent | 200 vs 404 |
| Email reset with an existing email vs not | Email send delay |
| Endpoint with cache HIT vs MISS | Cache latency |
| Endpoint with N rows (pagination) | Render time |
Anti-timing-detection: use cache eviction
If the browser caches the responses, the second request is ~0ms. To avoid it:
const url = `https://target.com/api/me?bust=${Math.random()}`;
And measure multiple times to average out network jitter.
Channel 2 — Error-based leaks
Some cross-origin resources fire onerror / onload on <script>, <img>, <link> depending on the response. Although you can't read the content, you can detect whether the response was 200, 404, parseable or not.
Script tag onerror/onload differential
<script src="https://target.com/api/private/secret-id-12345"
onload="known()" onerror="notFound()"></script>
- If the endpoint returns valid JS (200, content-type js) →
onload. - If it returns 404 →
onerror. - If it returns invalid JSON as JS →
onerror.
It gives an oracle: "does ID 12345 exist in the target for this user?"
Image dimensions leak
const img = new Image();
img.onload = () => console.log(img.naturalWidth, img.naturalHeight);
img.src = 'https://target.com/avatar/admin';
If admin avatars have a different size than regular ones → leak.
CSS load differential
<link rel="stylesheet" href="https://target.com/themes/admin.css"
onload="isAdmin()" onerror="notAdmin()">
CSS dynamically generated by user state → now detectable.
Channel 3 — Frame counting
Until recently, window.length (the number of iframes in a page) was leakable cross-origin if you embedded the page. Mitigated in modern browsers via COOP, but it still works against apps without COOP.
const w = window.open('https://target.com/dashboard');
setTimeout(() => {
console.log(w.length); // Número de iframes en el dashboard
// Apps que tienen iframes condicionales (e.g., "Admin panel" solo para admins) leakan rol
w.close();
}, 2000);
Variant with <object> or <iframe> + onload
If the browser blocks the load due to X-Frame-Options: DENY, it fires onerror; if not, onload:
<iframe src="https://target.com/admin" onload="canFrame()" onerror="cannotFrame()"></iframe>
X-Frame-Options may be set conditionally by the server (some apps emit it only for protected pages) → direct leak of auth state.
Channel 4 — CSP violation reports (the premium)
CSP report endpoints are one of the cleanest and least patched XS-Leaks. If the attacker hosts a page with a CSP that points the report-uri at their own endpoint, any CSP violation generated by loading cross-origin content is reported to the attacker.
Keep reading the full chain
The remaining part includes the step-by-step PoC, exploitation code and the full chain that led to impact. Available to subscribers.
Practice this in a lab
Xs Leaks Timing
Keep learning · free account
Save your progress, unlock advanced payloads and rank your flags.