You are viewing a preview of this lesson. Sign in to start learning
Back to Web Security: The Modern Browser Model

Cross-Origin Read Blocking

Understand how browsers prevent cross-origin data leaks through resource type inspection

Understanding Cross-Origin Read Blocking (CORB): The Browser's Defense Against Spectre

Imagine a malicious website silently reading your email, your bank account details, or your private messagesβ€”all without ever appearing to navigate away from its innocent-looking page. For years, web developers relied on the Same-Origin Policy and CORS (Cross-Origin Resource Sharing) to prevent exactly this scenario. But in January 2018, the discovery of Spectre and Meltdown vulnerabilities shattered assumptions about what attackers could access within a browser's memory. Suddenly, even blocked resources could leak sensitive data through clever CPU-level attacks. This lesson introduces you to Cross-Origin Read Blocking (CORB), the browser's crucial defense mechanism designed specifically to combat these speculative side-channel attacks. You'll find free flashcards embedded throughout to help reinforce these critical security concepts.

The Spectre Problem: When Process Isolation Isn't Enough

To understand why CORB exists, we need to grasp the fundamental problem it solves. Traditional web security assumed that if a browser blocked a cross-origin request (via CORS), the malicious page couldn't access that data. But Spectre changed everything.

🎯 Key Principle: Spectre exploits speculative execution in modern CPUs to read memory that should be inaccessible, even within the same process. If sensitive data from another origin enters your browser processβ€”even temporarilyβ€”an attacker might extract it through timing attacks.

Here's the threat scenario:

<!-- Malicious page attempts to load sensitive data -->
<script>
  // Attacker embeds a resource from victim.com
  fetch('https://victim.com/api/private-messages.json')
    .then(response => response.json())
    .catch(err => {
      // CORS blocks this! The attacker can't read the response...
      // But the data ALREADY entered the renderer process!
      // Spectre could potentially extract it from memory
    });
</script>

Even though CORS blocks the JavaScript from reading the response, the sensitive JSON data was downloaded and briefly resided in the browser's memory. A Spectre attack running in that same process could potentially read that memory through side-channel timing analysis.

πŸ’‘ Real-World Example: In 2018, researchers demonstrated that a malicious website could use Spectre to read pixels from cross-origin images, authentication tokens from JSON responses, and other sensitive dataβ€”all without violating traditional security boundaries.

CORB vs. CORS: Complementary Defenses

Many developers initially confuse CORB with CORS, but they operate at fundamentally different layers and solve different problems:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              CORS (Cross-Origin Resource Sharing)       β”‚
β”‚  Layer: JavaScript API                                  β”‚
β”‚  Goal: Control which origins can READ responses         β”‚
β”‚  When: After resource enters process                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        ⬇️
                  Response loaded
                  into memory ❌
                        ⬇️
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         CORB (Cross-Origin Read Blocking)               β”‚
β”‚  Layer: Network/Browser internals                       β”‚
β”‚  Goal: Prevent sensitive data from ENTERING process     β”‚
β”‚  When: Before resource is made available to renderer    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

CORS is permission-based: "Can this JavaScript code read this response?" CORB is content-based: "Should this sensitive data even enter this page's process?"

πŸ€” Did you know? CORB was originally called "Cross-Origin Read Blocking for Web Browsers" and was implemented as an emergency security response within months of the Spectre disclosure.

The Threat Model: Cross-Origin Embedding Attacks

CORB specifically protects against cross-origin embedding attacks. These occur when a malicious page tries to embed resources from other origins using HTML tags that accept cross-origin resources:

<!-- Traditional cross-origin embedding (normally allowed) -->
<img src="https://victim.com/profile-pic.jpg">     <!-- Images OK -->
<script src="https://cdn.example.com/lib.js"></script> <!-- Scripts OK -->
<link rel="stylesheet" href="https://cdn.example.com/style.css"> <!-- CSS OK -->

<!-- Malicious attempts to embed sensitive data -->
<script src="https://victim.com/api/messages.json"></script>
<!-- ⚠️ JSON loaded as script! CORB blocks this -->

<img src="https://victim.com/api/account-details.xml">
<!-- ⚠️ XML loaded as image! CORB blocks this -->

Without CORB, attackers could use these tags to force sensitive resources into their process, then exploit Spectre to extract data. The browser would load the resource, fail to parse it (JSON isn't valid JavaScript, XML isn't a valid image), but the damage would be doneβ€”the data entered the process.

Protected Resource Types

CORB focuses on protecting three primary resource types that commonly contain sensitive data:

πŸ“‹ Quick Reference Card:

πŸ”’ Resource Type πŸ“ MIME Types 🎯 Common Use Cases
πŸ”’ HTML text/html User dashboards, private pages
πŸ”’ JSON application/json, text/json API responses with user data
πŸ”’ XML application/xml, text/xml SOAP APIs, data feeds

🎯 Key Principle: CORB only blocks resources when there's a MIME type mismatchβ€”when a sensitive content type (HTML, JSON, XML) is being loaded in a context where it shouldn't be (like a <script> tag requesting JSON).

⚠️ Common Mistake 1: Thinking CORB blocks ALL cross-origin requests ⚠️

❌ Wrong thinking: "CORB prevents my site from loading any external resources."

βœ… Correct thinking: "CORB prevents sensitive data types (HTML/JSON/XML) from being loaded in inappropriate contexts (script tags, image tags, etc.)."

Real-World Impact on Browser Architecture

The introduction of CORB represented a significant shift in browser security architecture. Modern browsers now perform content sniffing at the network layerβ€”before content reaches the renderer processβ€”to determine if a response should be blocked.

This architectural change had profound implications:

πŸ”§ Browser Implementation Changes:

  • Network stack must parse response headers and sometimes response bodies
  • Additional CPU overhead for content-type validation
  • New telemetry to track CORB activation rates

πŸ”’ Security Improvements:

  • Defense-in-depth against Spectre and future CPU vulnerabilities
  • Reduced attack surface for cross-site data leaks
  • Protection even when developers misconfigure CORS

πŸ’‘ Pro Tip: CORB works transparently for properly configured web applications. If your APIs serve JSON with correct Content-Type: application/json headers and are only accessed via legitimate fetch() or XMLHttpRequest calls, CORB won't interfere. It only blocks suspicious cross-origin embedding attempts.

🧠 Mental Model: Think of CORB as a security guard at the entrance to a building (the browser process). CORS is like a security guard inside the building, checking if you can access specific rooms. CORB asks: "Should you even enter the building with that suspicious package?" CORS asks: "Now that you're inside, can you open this particular door?"

The introduction of CORB marked a turning point in web securityβ€”a recognition that traditional origin-based protections weren't sufficient against hardware-level vulnerabilities. In the next section, we'll dive deep into the technical mechanisms CORB uses to detect and block these suspicious resource loads, including the sophisticated content sniffing algorithms that determine what gets blocked and what passes through.

How CORB Works: Detection, Blocking, and MIME Type Sniffing

Now that we understand why CORB exists, let's explore the fascinating technical machinery that makes it work. CORB operates as a browser-side filter that intercepts cross-origin resource loads and applies a sophisticated algorithm to determine whether the response should reach the requesting page's memory space.

The CORB Decision Algorithm

🎯 Key Principle: CORB only protects sensitive MIME types loaded through cross-origin, no-CORS requests into opaque contexts like <script>, <img>, or <link> tags.

When your browser receives a cross-origin response, it follows this decision tree:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Cross-Origin Response Arrives     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
               β–Ό
      Is this a CORS request?
      (fetch with mode: 'cors')
               β”‚
         β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”
        YES          NO
         β”‚            β”‚
    Allow it    Continue CORB
                     β”‚
                     β–Ό
         Is Content-Type protected?
         (HTML/JSON/XML)
                     β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”
             YES            NO
              β”‚              β”‚
         Apply sniff    Allow it
         heuristics         β”‚
              β”‚              β”‚
              β–Ό              β”‚
      Confirm it's       β”Œβ”€β”€β”€β”˜
      really sensitive?  β”‚
              β”‚           β”‚
         β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”     β”‚
        YES       NO     β”‚
         β”‚         β”‚     β”‚
      BLOCK!   Allow  Allow

The algorithm focuses on three protected MIME types that typically contain sensitive data:

πŸ”’ text/html - User-specific HTML pages πŸ”’ application/json and text/json - API responses with private data πŸ”’ text/xml and application/xml - XML-formatted sensitive content

MIME Type Validation and Content-Type Headers

The Content-Type header is CORB's first line of defense. When a server sends a response, this header declares what type of content is being delivered. Let's see how different scenarios play out:

// Scenario 1: Legitimate cross-origin image (ALLOWED)
<img src="https://other-site.com/profile.jpg">
// Server sends: Content-Type: image/jpeg
// Result: βœ… Allowed - images aren't protected types

// Scenario 2: Malicious attempt to load JSON as script (BLOCKED)
<script src="https://bank.com/api/transactions.json"></script>
// Server sends: Content-Type: application/json
// Result: ❌ BLOCKED by CORB - JSON is protected

// Scenario 3: JSON loaded via proper CORS (ALLOWED)
fetch('https://api.example.com/data.json', {
  mode: 'cors',
  credentials: 'include'
})
// Server sends: Content-Type: application/json
//              Access-Control-Allow-Origin: *
// Result: βœ… Allowed - proper CORS request

⚠️ Common Mistake: Developers sometimes serve JSON with Content-Type: text/plain to "bypass" security. CORB is smarter than thatβ€”it performs content sniffing to catch mislabeled resources.

The X-Content-Type-Options: nosniff Directive

The X-Content-Type-Options: nosniff header tells browsers to trust the Content-Type header absolutely, without second-guessing through content sniffing. This header creates an interesting interaction with CORB:

HTTP/1.1 200 OK
Content-Type: text/html
X-Content-Type-Options: nosniff

{"user": "alice", "balance": 5000}

In this example, the server claims the content is HTML (with nosniff), but sends JSON. CORB will:

  1. See the nosniff directive
  2. Trust that it's HTML without sniffing
  3. Block the resource because HTML is a protected type

πŸ’‘ Pro Tip: Always use X-Content-Type-Options: nosniff on your APIs. It prevents MIME confusion attacks and makes CORB's job easier, resulting in better performance.

Content Sniffing Heuristics

When a server doesn't send nosniff, CORB performs content sniffingβ€”examining the actual response body to detect if it's truly a sensitive type. This protects against misconfigured servers or attack attempts.

HTML Detection: CORB looks for the first non-whitespace characters in the response. If it finds <!DOCTYPE, <html, <script, <head, <body, or other HTML tags, it confirms the content as HTML.

JSON Detection: The response must start with a JSON security prefix or valid JSON structure:

// These patterns trigger JSON detection:

// 1. Standard JSON array or object
[{"userId": 123, "email": "user@example.com"}]
{"secret": "abc123"}

// 2. JSON with security prefix (prevents XSSI)
)]}'\n{"data": "sensitive"}

// These do NOT trigger JSON detection:
"just a string"  // Top-level strings aren't protected
12345            // Top-level numbers aren't protected

XML Detection: CORB checks if the response begins with <?xml or has an XML namespace declaration.

πŸ€” Did you know? The content sniffing algorithm only examines the first 1024 bytes of a response. This keeps performance overhead minimal while catching the vast majority of cases.

Real-World Examples: Blocked vs. Allowed Requests

Let's examine concrete scenarios where CORB intervenes:

<!-- Example 1: Attacker tries to steal user data -->
<script src="https://victim-site.com/api/user/private-info"></script>

Server Response:

HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: sessionid=abc123

{"ssn": "123-45-6789", "email": "victim@email.com"}

CORB Action: ❌ BLOCKED - The response is replaced with an empty body. The attacker's JavaScript never sees the sensitive data.

<!-- Example 2: Legitimate image embedding -->
<img src="https://cdn.example.com/avatar.png">

Server Response:

HTTP/1.1 200 OK
Content-Type: image/png

[PNG binary data...]

CORB Action: βœ… ALLOWED - Images aren't sensitive MIME types, so CORB permits the load.

// Example 3: Modern API call with proper CORS
fetch('https://api.service.com/data', {
  method: 'GET',
  mode: 'cors',  // Explicit CORS mode
  credentials: 'include'
}).then(r => r.json());

Server Response:

HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: https://your-site.com
Access-Control-Allow-Credentials: true

{"data": "accessible"}

CORB Action: βœ… ALLOWED - This is a proper CORS request with server consent, so CORB doesn't interfere.

Identifying CORB in Browser DevTools

When CORB blocks a resource, modern browsers provide clear indicators in the Network tab. Here's what to look for:

Chrome/Edge DevTools:

  • The request appears with status 200 OK (it was fetched)
  • Console shows: ⚠️ Cross-Origin Read Blocking (CORB) blocked cross-origin response
  • The Size column shows 0 B or (CORB)
  • Response body is empty when inspected

Firefox DevTools:

  • Console message: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource
  • Network entry shows the request but response preview is empty

πŸ’‘ Real-World Example: You're debugging why your dashboard isn't loading data. You check DevTools and see a CORB warning on your API request. The issue? You're using <script src="/api/data"> instead of fetch(). Switching to a proper CORS-enabled fetch request solves the problem immediately.

πŸ“‹ Quick Reference: CORB Decision Factors

Factor Blocks? Notes
πŸ”’ HTML/JSON/XML MIME βœ… Yes Only if cross-origin no-CORS
πŸ–ΌοΈ Images/CSS/JS MIME ❌ No Not sensitive types
🌐 CORS fetch request ❌ No Server explicitly allows
πŸ” Content-Type mismatch βœ… Maybe Triggers content sniffing
πŸ›‘οΈ X-Content-Type-Options βœ… Enforced Prevents sniffing workarounds

⚠️ Common Mistake: Assuming CORB blocks all cross-origin requests. CORB is surgicalβ€”it only blocks sensitive content types loaded through contexts that shouldn't access them. Properly configured CORS requests work perfectly.

Implementing CORB-Compliant Applications and Troubleshooting Common Issues

Ensuring your web applications work seamlessly with Cross-Origin Read Blocking requires understanding proper resource configuration and recognizing common pitfalls. When CORB blocks a resource, it's typically because the browser detected a MIME type mismatch or potentially sensitive content being loaded in a cross-origin context. Let's explore how to build CORB-compliant applications and troubleshoot issues effectively.

Best Practices: Setting Correct Content-Type Headers

🎯 Key Principle: The most critical step in CORB compliance is serving resources with accurate Content-Type headers that match the actual content.

Your API endpoints should always return the appropriate MIME type for their response format. For JSON APIs, this means setting Content-Type: application/json. Here's how to configure this correctly across different server environments:

// Node.js/Express - Correct JSON API response
app.get('/api/users', (req, res) => {
  // βœ… Explicitly set the correct Content-Type
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('X-Content-Type-Options', 'nosniff');
  
  const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
  res.json(users);
});

// ❌ WRONG - Default handler might return text/html
app.get('/api/data', (req, res) => {
  res.send(JSON.stringify({ data: 'sensitive' })); // May inherit wrong MIME type
});
## Python/Flask - Proper header configuration
from flask import Flask, jsonify, make_response

app = Flask(__name__)

@app.route('/api/transactions')
def get_transactions():
    # βœ… jsonify() automatically sets application/json
    response = jsonify([
        {'id': 1, 'amount': 100.50},
        {'id': 2, 'amount': 250.00}
    ])
    # Add nosniff to prevent MIME sniffing
    response.headers['X-Content-Type-Options'] = 'nosniff'
    return response

πŸ’‘ Pro Tip: Modern frameworks like Express and Flask automatically set correct Content-Type headers when using their JSON response methods (res.json(), jsonify()), but always verify your headers in production.

Understanding X-Content-Type-Options: nosniff

The X-Content-Type-Options: nosniff header instructs browsers to strictly follow the declared Content-Type without attempting MIME sniffing. This is crucial for CORB because it prevents the browser from second-guessing your content type and ensures CORB's detection algorithm works correctly.

HTTP/1.1 200 OK
Content-Type: application/json
X-Content-Type-Options: nosniff
Access-Control-Allow-Origin: https://trusted-site.com

{"userId": 123, "balance": 5000}

🎯 Key Principle: Always combine X-Content-Type-Options: nosniff with accurate Content-Type headers. This creates a strong contract between your server and the browser about what content type to expect.

When to use nosniff:

  • πŸ”’ All API endpoints returning JSON, XML, or other structured data
  • πŸ”’ Any endpoint serving potentially sensitive information
  • πŸ”’ File downloads where content type matters for security
  • πŸ”’ Resources that should never be interpreted as HTML/scripts

Common Pitfall: JSON with text/html MIME Type

⚠️ Common Mistake: Mistake 1: Serving JSON with text/html Content-Type ⚠️

This is the most frequent CORB-related issue developers encounter. It typically happens when:

❌ Wrong thinking: "The browser will figure out it's JSON from the content." βœ… Correct thinking: "I must explicitly declare the correct MIME type to prevent CORB blocking."

Common scenarios where this occurs:

  1. Using generic response handlers that default to HTML
  2. Template engines interfering with API responses
  3. Reverse proxies overwriting Content-Type headers
  4. Legacy code that predates modern API standards

How to fix it:

// Before: Generic route handler
app.get('/legacy-api', (req, res) => {
  // ❌ This might send as text/html depending on framework defaults
  res.send('{"status":"ok"}');
});

// After: Explicitly set headers
app.get('/legacy-api', (req, res) => {
  // βœ… Force correct MIME type
  res.type('application/json');
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.send('{"status":"ok"}');
});

// Best: Use framework JSON methods
app.get('/modern-api', (req, res) => {
  res.json({status: 'ok'}); // βœ… Handles everything correctly
});

Debugging CORB Warnings in Chrome/Edge DevTools

When CORB blocks a resource, Chrome and Edge display distinctive warning messages in the DevTools Console. Learning to interpret these warnings is essential for rapid troubleshooting.

Typical CORB warning:

Cross-Origin Read Blocking (CORB) blocked cross-origin response 
https://api.example.com/users with MIME type text/html. 
See https://www.chromestatus.com/feature/5629709824032768 for more details.

Debugging workflow:

1. Open DevTools β†’ Network tab
   ↓
2. Locate the blocked request (often shows status 200)
   ↓
3. Check Response Headers:
   - Content-Type: Is it correct?
   - X-Content-Type-Options: Is nosniff present?
   ↓
4. Preview response body: Does it match Content-Type?
   ↓
5. Check Console for CORB warnings
   ↓
6. Fix server headers and test again

πŸ’‘ Real-World Example: A developer noticed their dashboard wasn't loading user data. DevTools showed:

  • Network tab: GET /api/users β†’ Status 200
  • Console: CORB warning about text/html MIME type
  • Headers tab: Content-Type: text/html; charset=utf-8
  • Preview tab: Valid JSON content [{"id":1,...}]

The issue was their server's default Content-Type for all routes. Adding res.type('application/json') resolved it immediately.

πŸ€” Did you know? CORB will still block resources even if they return successfully (200 OK). The blocking happens after the network request completes but before the content reaches JavaScript, making it invisible to fetch() or XMLHttpRequest.

Migration Strategies for Legacy Applications

Legacy applications that relied on cross-origin resource inclusion need careful migration to work with CORB. Here are proven strategies:

Strategy 1: Audit and Fix MIME Types

  • πŸ”§ Inventory all API endpoints and their actual content
  • πŸ”§ Update server configurations to set correct Content-Type headers
  • πŸ”§ Add X-Content-Type-Options: nosniff universally for APIs

Strategy 2: Implement Proper CORS for Legitimate Cross-Origin Access

// If you need legitimate cross-origin access, use CORS
app.use('/api', (req, res, next) => {
  // Only allow specific trusted origins
  const allowedOrigins = ['https://app.example.com', 'https://admin.example.com'];
  const origin = req.headers.origin;
  
  if (allowedOrigins.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
    res.setHeader('Access-Control-Allow-Credentials', 'true');
  }
  
  // Ensure correct content type
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('X-Content-Type-Options', 'nosniff');
  
  next();
});

Strategy 3: Refactor Cross-Origin Resource Embedding

  • πŸ“š Move resources to same-origin when possible
  • πŸ“š Use server-side proxying for legitimate cross-origin needs
  • πŸ“š Implement proper authentication/authorization instead of relying on resource blocking

⚠️ Common Mistake: Mistake 2: Trying to disable CORB ⚠️

You cannot disable CORBβ€”it's a browser security feature. The solution is always to fix your resource headers, not try to circumvent the protection.

CORB and Cross-Origin Resource Policy (CORP)

CORB works alongside Cross-Origin Resource Policy (CORP) as part of the modern web security model. Understanding their interaction helps you implement comprehensive protection:

πŸ“‹ Quick Reference Card: CORB vs CORP

Feature πŸ›‘οΈ CORB πŸ” CORP
Purpose 🎯 Automatic protection against Spectre-style attacks 🎯 Explicit opt-in resource isolation
Scope 🌐 HTML, JSON, XML cross-origin responses 🌐 All resource types
Control πŸ€– Browser-determined (automatic) πŸ‘€ Server-specified (explicit header)
Header βš™οΈ Uses Content-Type + X-Content-Type-Options βš™οΈ Uses Cross-Origin-Resource-Policy
Default βœ… Always active ❌ Opt-in only

Complementary security configuration:

// Maximum security for sensitive API endpoint
app.get('/api/sensitive-data', (req, res) => {
  // CORB protection via correct MIME type
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('X-Content-Type-Options', 'nosniff');
  
  // CORP: Explicit same-origin policy
  res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');
  
  // Additional security headers
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader('Content-Security-Policy', "default-src 'none'");
  
  res.json({ sensitiveData: 'protected' });
});

πŸ’‘ Pro Tip: Use CORP's same-origin value for highly sensitive resources, same-site for resources shared across subdomains, and cross-origin only when necessary with proper CORS configuration.


Summary

You now understand how to build and maintain CORB-compliant web applications. Before this section, you might have been confused by mysterious "CORB blocked" warnings or unsure why cross-origin resources weren't loading. Now you can:

What you've mastered:

  • 🧠 Setting correct Content-Type headers for all API endpoints
  • 🧠 Using X-Content-Type-Options: nosniff to prevent MIME confusion
  • 🧠 Identifying and fixing the common JSON-as-HTML pitfall
  • 🧠 Debugging CORB issues efficiently using browser DevTools
  • 🧠 Migrating legacy applications to CORB-compliant architectures
  • 🧠 Combining CORB with CORP for layered security

⚠️ Critical points to remember:

  • ⚠️ Always set accurate Content-Type headersβ€”this is the foundation of CORB compliance
  • ⚠️ Add X-Content-Type-Options: nosniff to all API responses to prevent browser MIME sniffing
  • ⚠️ CORB cannot be disabledβ€”fix your headers instead of trying to work around it
  • ⚠️ CORB blocking happens silentlyβ€”the request succeeds but content is blocked from JavaScript

Practical next steps:

  1. Audit your APIs: Run a scan of all your API endpoints and verify they return correct Content-Type headers. Use browser DevTools or automated tools to check each endpoint.

  2. Implement defense in depth: Combine CORB-compliant headers with CORP headers (Cross-Origin-Resource-Policy: same-origin) for your most sensitive endpoints to create multiple layers of protection.

  3. Monitor and test: Set up monitoring to catch CORB warnings in production. Use tools like Chrome's DevTools Protocol or Sentry to track when resources are blocked, helping you identify issues before users report them.

By following these practices, you'll ensure your applications work seamlessly with modern browser security features while protecting your users from sophisticated attacks like Spectre.