XS-Leak (Cross-Site Leak)

XS-Leak (Cross-Site Leak) is a class of vulnerabilities that allow attackers to infer sensitive information about users by exploiting browser side-channel behaviors, timing differences, or observable events across origins.

How It Works

While Same-Origin Policy prevents direct reading of cross-origin responses, attackers can still detect characteristics like response size, load timing, redirect behavior, or error conditions. These side channels can leak information about a user's state or data on other sites.

Common XS-Leak Techniques

Frame Counting

// Count iframes in cross-origin page to detect state
const win = window.open('https://target.com/search?q=secret');
setTimeout(() => {
  if (win.frames.length > 0) {
    // Search returned results
  }
}, 1000);

Timing Attacks

// Measure response time to infer data
const start = performance.now();
fetch('https://target.com/api/check?email=victim@example.com', {
  mode: 'no-cors',
  credentials: 'include'
}).then(() => {
  const time = performance.now() - start;
  // Longer time may indicate user exists
});

Error Events

// Detect resource existence via load/error events
const img = new Image();
img.onload = () => { /* Resource exists */ };
img.onerror = () => { /* Resource doesn't exist or error */ };
img.src = 'https://target.com/profile/picture?id=123';

Leaked Information Examples

  • Whether a user is logged in to a service
  • User's email or username on other sites
  • Search results or query matches
  • Social connections or group memberships

Prevention

  • Cross-Origin-Opener-Policy (COOP): same-origin prevents cross-origin windows from retaining references
  • Cross-Origin-Resource-Policy (CORP): same-origin or same-site prevents cross-origin embedding
  • Cross-Origin-Embedder-Policy (COEP): require-corp enforces CORP on all subresources
  • SameSite Cookies: SameSite=Strict prevents cookies from being sent on cross-site requests
  • Fetch Metadata Headers: Use Sec-Fetch-Site, Sec-Fetch-Mode to reject suspicious requests server-side
  • Cache-Control: no-store on sensitive responses prevents cache-based leaks
  • Framing Protection: X-Frame-Options: DENY or CSP frame-ancestors 'none'

See Also