XS-Leaks (Cross-Site Leaks)
XS-Leaks abuse browser primitives that leak information ACROSS origins. Attacker page can observe whether a cross-origin GET returned different content based on victim's authenticated state. Smaller than full cross-origin read (which is blocked), but enough to enumerate identifiers, detect membership, learn search-result presence.
1. Categories
1.1 Timing oracles
Cross-origin fetch / image load timing varies by server response size. Attacker measures load time → infers content.
const start = performance.now();
const img = new Image();
img.onerror = () => console.log(performance.now() - start);
img.src = 'https://target.com/api/users/me/notifications';
1.2 Frame counting (window.frames.length)
Some pages embed N iframes when authenticated and 0 when not. Attacker
iframes target page and reads iframe.contentWindow.frames.length.
1.3 Window name / postMessage leak
iframe.contentWindow.name is preserved across navigation. Some pages
set it w/ user-identifying data.
1.4 Error-event oracle
<img src=target.com/api/user/{id}/data> triggers different onerror
behavior based on response code (403 vs 404 vs 200 w/ image content-type).
1.5 CSS injection style oracle
<link rel=stylesheet href=target.com/page> — different applied styles
leak state via getComputedStyle of attacker page.
1.6 Search result presence
Many search endpoints return cached/non-cached headers indicating hits. Attacker measures cache hit vs miss timing for guessed search terms.
1.7 ID guessability (XS-Search)
for (const guessed_id of guessable_set) {
const url = `https://target.com/api/user/${guessed_id}`;
// measure timing or frame-count differential
}
2. xsleaks.dev — canonical reference
Full taxonomy + browser-version compatibility matrix: https://xsleaks.dev/
Decepticon agents should consult this for current technique viability — browser mitigations evolve fast (COOP, COEP, Cross-Origin-Opener-Policy).
3. Detection
// Frame count
const f = document.createElement('iframe');
f.src = 'https://target.com/dashboard'; // attacker hosts this in own page
document.body.appendChild(f);
f.onload = () => {
console.log('frames:', f.contentWindow.frames.length);
};
// Timing
async function timeFetch(url) {
const t = performance.now();
try { await fetch(url, {mode:'no-cors', credentials:'include'}); } catch {}
return performance.now() - t;
}
4. PoC framing
XS-Leak PoCs require:
- Attacker host (your own controlled domain)
- Victim browser with authenticated session to target
- Visual demonstration of leaked info (e.g. infer victim's email, search history, friend list)
Document the attack page, record video of victim browser visiting it → inferred information displayed.
5. Severity
| Bug | Severity |
|---|---|
| XS-Search enumerating victim's private documents | High 7-8 |
| Frame-count revealing logged-in state | Medium 5-6 |
| Timing oracle inferring victim email / ID | High 7-8 |
| Window.name leaking session info | High 7-8 |
| Cross-origin error-event leaking which users exist | Medium 4-5 |
6. Defender
- Set
Cross-Origin-Opener-Policy: same-origin - Set
Cross-Origin-Embedder-Policy: require-corp - Set
Cross-Origin-Resource-Policy: same-origin - Disable iframe embedding for sensitive pages:
X-Frame-Options: DENYorframe-ancestors 'none'in CSP - Constant-time responses for sensitive endpoints (esp. when state-dependent)
Vary: Cookie+ careful caching
Cross-references
- Upstream:
skills/_corpus/payloads/XS-Leak/ - xsleaks.dev — primary reference
- DOM clobbering overlap (different class, same client-side mindset):
skills/exploit/web/dom-clobbering/SKILL.md