Claude Skills Guide

Cross-Origin Resource Sharing (CORS) errors are a common obstacle when developing web applications that communicate with APIs. If you’ve worked on frontend projects that fetch data from external services, you’ve likely encountered the dreaded “No ‘Access-Control-Allow-Origin’ header” error. This guide shows you how to create a Chrome extension that helps manage CORS restrictions during development workflows.

Understanding the CORS Problem in Development

When your application running on localhost:3000 tries to fetch data from an API at api.example.com, browsers block the request due to the Same-Origin Policy. This security mechanism prevents malicious scripts from accessing resources on different domains, but it also blocks legitimate development requests.

Chrome extensions have a significant advantage over regular web pages: they can make cross-origin requests without being subject to the same CORS restrictions. This is because extension contexts are treated differently by the browser security model. However, there are still specific patterns you need to follow to implement this correctly.

Building Your CORS Helper Extension

The core of a CORS unblock extension relies on the web_accessible_resources manifest key and background scripts that proxy requests. Here’s a practical implementation:

Manifest Configuration (manifest.json)

{
  "manifest_version": 3,
  "name": "CORS Dev Helper",
  "version": "1.0.0",
  "description": "Helps bypass CORS during development",
  "permissions": [
    "activeTab",
    "scripting",
    "nativeMessaging"
  ],
  "host_permissions": [
    "<all_urls>"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icon16.png",
      "48": "icon48.png",
      "128": "icon128.png"
    }
  }
}

Background Script (background.js)

The background script acts as a proxy, handling requests that would otherwise be blocked:

// background.js - Handles cross-origin requests from content scripts
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'fetchProxy') {
    fetch(request.url, {
      method: request.method || 'GET',
      headers: request.headers || {},
      body: request.body ? JSON.stringify(request.body) : undefined
    })
    .then(response => response.json())
    .then(data => sendResponse({ success: true, data }))
    .catch(error => sendResponse({ success: false, error: error.message }));
    return true; // Keep channel open for async response
  }
});

Content Script Integration

From your web application, you communicate with the extension to make cross-origin requests:

// In your web application - call this instead of fetch()
async function corsFetch(url, options = {}) {
  return new Promise((resolve, reject) => {
    chrome.runtime.sendMessage({
      action: 'fetchProxy',
      url: url,
      method: options.method || 'GET',
      headers: options.headers || {},
      body: options.body
    }, (response) => {
      if (response.success) {
        resolve(response.data);
      } else {
        reject(new Error(response.error));
      }
    });
  });
}

// Usage example
const data = await corsFetch('https://api.example.com/data', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: { key: 'value' }
});

Alternative Approaches

There are several ways to handle CORS during development, each with trade-offs:

Server-Side Proxy

Set up a simple Node.js proxy:

// server.js - Simple proxy server
const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors());
app.use('/proxy/:url(*)', async (req, res) => {
  const targetUrl = req.params.url;
  const response = await fetch(targetUrl);
  const data = await response.json();
  res.json(data);
});

app.listen(3001);

Browser Flags

For quick testing, you can launch Chrome with security disabled:

# macOS
open -a Google\ Chrome --args --disable-web-security --user-data-dir

# Linux
google-chrome --disable-web-security

# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security

This approach is useful for rapid debugging but should never be used in production or on machines with sensitive data.

Security Considerations

Building a CORS bypass extension requires careful security thinking:

Restrict to Development Environments: Add checks to ensure requests only go to known development URLs. You can store allowed domains in extension storage:

// background.js - Domain validation
const ALLOWED_DEV_DOMAINS = ['localhost', '127.0.0.1', '*.dev'];

function isDevUrl(url) {
  return ALLOWED_DEV_DOMAINS.some(domain => 
    url.includes(domain) || new URL(url).hostname.endsWith(domain.replace('*', ''))
  );
}

Validate All Inputs: Never blindly proxy requests. Validate URLs, methods, and content to prevent your extension from being used as an open proxy.

Use HTTPS in Production: Even for development proxies, establish secure connections to avoid exposing sensitive credentials.

Advanced: Programmatic Header Injection

For more complex scenarios, you might need to modify headers programmatically:

// background.js - Header manipulation
chrome.webRequest.onBeforeRequest.addListener(
  (details) => {
    if (details.url.includes('api.dev.local')) {
      return {
        redirectUrl: details.url + 
          (details.url.includes('?') ? '&' : '?') + 
          'cors-bypass=true'
      };
    }
  },
  { urls: ["<all_urls>"] },
  ["blocking"]
);

This approach intercepts requests at the network level, allowing you to add custom headers or modify request behavior.

Deployment and Testing

When your extension is ready:

  1. Enable Developer Mode in chrome://extensions
  2. Click “Load unpacked” and select your extension directory
  3. Test with a simple fetch call to verify the proxy works
  4. Check the background script console for any errors

When to Use Each Approach

For most development scenarios, consider this decision tree:

Chrome extensions give you the most flexibility for local development, while server-side solutions scale better for team environments.


Built by theluckystrike — More at zovo.one