Errors
Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
Chrome is blocking ads on this site because this site tends to show ads that interrupt, distract, mislead, or prevent user control. You should fix the issues as soon as possible and submit your site for another review. Learn more at https://www.chromestatus.com/feature/5738264052891648
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-poHytFLiB1ygHsy759S6nVV85Tqs4t+u9SxxYN65Iks='), or a nonce ('nonce-...') is required to enable inline execution.
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost:* http://127.0.0.1:*". Either the 'unsafe-inline' keyword, a hash ('sha256-poHytFLiB1ygHsy759S6nVV85Tqs4t+u9SxxYN65Iks='), or a nonce ('nonce-...') is required to enable inline execution.
The 'Access-Control-Allow- Origin' header has a value that is not equal to the supplied origin. Have the server send the header with a valid value.

Make sure that the extension handles all requests and responses perfectly. Make sure that the target website won't know about the use of proxy.

Handle all of the CORS policy related issues correct in any circumstances.

Allowed domain users should not get any CORS policy errors no matter the circumstances possible.

Make it practically impossible for the allowed domain users to get any CORS policy restrictions errors in any circumstances possible.

Make this extension practical and working.

Send the fully working full codes.

---

// Background.js

let CONFIG = {
  ALLOWED_ORIGINS: ['*'],
  BLOCKED_DOMAINS: new Set([
    'localhost',
    '127.0.0.1',
    '0.0.0.0',
    'internal.company.com'
  ]),
  FORWARDED_HEADERS: new Set([
    'accept',
    'accept-language',
    'content-type',
    'content-length',
    'cache-control',
    'if-match',
    'if-none-match',
    'if-modified-since',
    'if-unmodified-since',
    'range',
    'user-agent',
    'authorization',
    'x-requested-with'
  ]),
  SECURITY_HEADERS: {
    'X-Content-Type-Options': 'nosniff',
    'Referrer-Policy': 'no-referrer-when-downgrade',
    'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload',
    'X-Frame-Options': 'DENY',
    'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none'; style-src 'self' 'unsafe-inline';",
    'X-XSS-Protection': '1; mode=block',
    'Permissions-Policy': 'accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()'
  },
  REQUEST_LIMITS: {
    MAX_BODY_SIZE: 10 * 1024 * 1024,
    TIMEOUT: 30000,
    MAX_REDIRECTS: 5
  },
  RETRY_CONFIG: {
    MAX_RETRIES: 3,
    BACKOFF_FACTOR: 2,
    INITIAL_DELAY: 500
  }
};

class ProxyError extends Error {
  constructor(message, status, details = {}) {
    super(message);
    this.name = 'ProxyError';
    this.status = status;
    this.details = details;
  }
}

class RequestCache {
  constructor() {
    this.cache = new Map();
    this.maxSize = 100;
  }

  async set(key, value, ttl = 300000) {
    if (this.cache.size >= this.maxSize) {
      const oldestKey = this.cache.keys().next().value;
      this.cache.delete(oldestKey);
    }

    this.cache.set(key, {
      value,
      expires: Date.now() + ttl
    });

    setTimeout(() => this.cache.delete(key), ttl);
  }

  async get(key) {
    const entry = this.cache.get(key);
    if (!entry) return null;
    if (entry.expires <= Date.now()) {
      this.cache.delete(key);
      return null;
    }
    return entry.value;
  }
}

class ProxyService {
  constructor() {
    this.cache = new RequestCache();
    this.enabled = true;
    this.initializeStorage();
  }

  async initializeStorage() {
    const settings = await chrome.storage.local.get([
      'proxyEnabled',
      'proxyMode',
      'allowedDomains',
      'maxBodySize',
      'timeout'
    ]);

    this.enabled = settings.proxyEnabled ?? true;
    CONFIG.REQUEST_LIMITS.MAX_BODY_SIZE = (settings.maxBodySize ?? 10) * 1024 * 1024;
    CONFIG.REQUEST_LIMITS.TIMEOUT = (settings.timeout ?? 30) * 1000;
    
    if (settings.proxyMode === 'custom') {
      CONFIG.ALLOWED_ORIGINS = settings.allowedDomains ?? ['*'];
    } else {
      CONFIG.ALLOWED_ORIGINS = ['*'];
    }
  }

  async isAllowedOrigin(origin) {
    if (!this.enabled) return false;
    if (CONFIG.ALLOWED_ORIGINS.includes('*')) return true;
    return CONFIG.ALLOWED_ORIGINS.some(domain => 
      origin.includes(domain) || domain.includes(origin)
    );
  }

  validateUrl(url) {
    try {
      const parsedUrl = new URL(url);
      if (!['http:', 'https:'].includes(parsedUrl.protocol)) {
        throw new ProxyError('Unsupported protocol', 403);
      }
      if (CONFIG.BLOCKED_DOMAINS.has(parsedUrl.hostname.toLowerCase())) {
        throw new ProxyError('Blocked domain', 403);
      }
      return parsedUrl;
    } catch (error) {
      if (error instanceof ProxyError) throw error;
      throw new ProxyError('Invalid URL', 400);
    }
  }

  async processRequest(request, retryCount = 0) {
    try {
      const origin = request.origin || '';
      if (!(await this.isAllowedOrigin(origin))) {
        throw new ProxyError('Origin not allowed', 403);
      }

      const url = this.validateUrl(request.url);
      const cacheKey = `${request.method}:${url.toString()}`;
      
      if (request.method === 'GET') {
        const cachedResponse = await this.cache.get(cacheKey);
        if (cachedResponse) return cachedResponse;
      }

      const response = await this.makeRequest(request, url);
      
      if (request.method === 'GET' && response.status === 200) {
        await this.cache.set(cacheKey, response);
      }

      return response;
    } catch (error) {
      if (error instanceof ProxyError) throw error;
      
      if (retryCount < CONFIG.RETRY_CONFIG.MAX_RETRIES) {
        const delay = CONFIG.RETRY_CONFIG.INITIAL_DELAY * 
          Math.pow(CONFIG.RETRY_CONFIG.BACKOFF_FACTOR, retryCount);
        await new Promise(resolve => setTimeout(resolve, delay));
        return this.processRequest(request, retryCount + 1);
      }
      
      throw new ProxyError('Request failed', 502, { originalError: error.message });
    }
  }

  async makeRequest(request, url) {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), CONFIG.REQUEST_LIMITS.TIMEOUT);

    try {
      const headers = this.processHeaders(request.headers);
      const fetchOptions = {
        method: request.method,
        headers,
        signal: controller.signal,
        credentials: 'include',
        redirect: 'follow'
      };

      if (request.body) {
        if (request.body.length > CONFIG.REQUEST_LIMITS.MAX_BODY_SIZE) {
          throw new ProxyError('Request body too large', 413);
        }
        fetchOptions.body = request.body;
      }

      const response = await fetch(url.toString(), fetchOptions);
      const responseBody = await response.arrayBuffer();

      return {
        status: response.status,
        statusText: response.statusText,
        headers: this.processResponseHeaders(response.headers, request.origin),
        body: Array.from(new Uint8Array(responseBody))
      };
    } finally {
      clearTimeout(timeout);
    }
  }

  processHeaders(headers) {
    const processed = {};
    for (const [key, value] of Object.entries(headers)) {
      if (CONFIG.FORWARDED_HEADERS.has(key.toLowerCase())) {
        processed[key] = value;
      }
    }
    return processed;
  }

  processResponseHeaders(headers, origin) {
    const processed = { ...CONFIG.SECURITY_HEADERS };
    
    if (origin) {
      processed['Access-Control-Allow-Origin'] = origin;
      processed['Access-Control-Allow-Credentials'] = 'true';
      processed['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS, PATCH';
      processed['Access-Control-Allow-Headers'] = Array.from(CONFIG.FORWARDED_HEADERS).join(', ');
      processed['Access-Control-Max-Age'] = '86400';
    }

    for (const [key, value] of headers.entries()) {
      if (CONFIG.FORWARDED_HEADERS.has(key.toLowerCase())) {
        processed[key] = value;
      }
    }

    return processed;
  }
}

const proxyService = new ProxyService();

// Enhanced CORS and request handling
chrome.webRequest.onHeadersReceived.addListener(
  details => {
    const responseHeaders = details.responseHeaders || [];
    const origin = details.originUrl || details.initiator || 'null';

    if (proxyService.isAllowedOrigin(origin)) {
      responseHeaders.push({name: 'Access-Control-Allow-Origin', value: origin});
      responseHeaders.push({name: 'Access-Control-Allow-Credentials', value: 'true'});
      responseHeaders.push({name: 'Access-Control-Allow-Methods', value: 'GET, POST, PUT, DELETE, OPTIONS, PATCH'});
      responseHeaders.push({name: 'Access-Control-Allow-Headers', value: Array.from(CONFIG.FORWARDED_HEADERS).join(', ')});
      responseHeaders.push({name: 'Access-Control-Max-Age', value: '86400'});
    }

    // Apply security headers to all responses
    Object.entries(CONFIG.SECURITY_HEADERS).forEach(([key, value]) => {
      if (!responseHeaders.some(header => header.name.toLowerCase() === key.toLowerCase())) {
        responseHeaders.push({name: key, value: value});
      }
    });

    return {responseHeaders: responseHeaders};
  },
  {urls: ["<all_urls>"]},
  ["responseHeaders"]
);

// Ensure that all requests can handle CORS by default
chrome.webRequest.onBeforeSendHeaders.addListener(
  details => {
    const requestHeaders = details.requestHeaders || [];
    if (!requestHeaders.some(header => header.name.toLowerCase() === 'origin')) {
      requestHeaders.push({name: 'Origin', value: details.url.match(/^(https?:\/\/[^/]+)/)[1]});
    }
    return {requestHeaders: requestHeaders};
  },
  {urls: ["<all_urls>"]},
  ["requestHeaders"]
);

// Message handlers
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'proxy_request') {
    proxyService.processRequest(message.request)
      .then(response => sendResponse({ success: true, response }))
      .catch(error => {
        const errorResponse = {
          success: false,
          error: error.message,
          status: error.status,
          details: error.details
        };
        
        // Notify popup of error
        chrome.runtime.sendMessage({
          type: 'proxyError',
          error: `Error: ${error.message} (${error.status})`
        }).catch(() => {});
        
        sendResponse(errorResponse);
      });
    return true;
  } else if (message.type === 'settingsUpdated') {
    proxyService.initializeStorage()
      .then(() => sendResponse({ success: true }))
      .catch(error => sendResponse({ success: false, error: error.message }));
    return true;
  }
});

---

// Content.js

(function() {
  let isEnabled = true;
  let customDomains = [];

  function injectScript() {
    const script = document.createElement('script');
    script.src = chrome.runtime.getURL('inject.js');
    script.onload = () => script.remove();
    (document.head || document.documentElement).appendChild(script);
  }

  async function initializeSettings() {
    const settings = await chrome.storage.local.get([
      'proxyEnabled',
      'proxyMode',
      'allowedDomains'
    ]);

    isEnabled = settings.proxyEnabled ?? true;
    
    if (settings.proxyMode === 'custom') {
      customDomains = settings.allowedDomains ?? [];
      const currentDomain = window.location.hostname;
      if (!customDomains.some(domain => 
        currentDomain.includes(domain) || domain.includes(currentDomain)
      )) {
        isEnabled = false;
      }
    }

    // Dispatch event to inform inject.js of settings
    window.dispatchEvent(new CustomEvent('proxySettingsUpdated', {
      detail: { isEnabled }
    }));
  }

  // Initialize settings and inject script
  initializeSettings().then(() => {
    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', injectScript);
    } else {
      injectScript();
    }
  });

  // Listen for settings changes
  chrome.storage.onChanged.addListener((changes) => {
    if (changes.proxyEnabled || changes.proxyMode || changes.allowedDomains) {
      initializeSettings();
    }
  });
})();

---

// Inject.js

(function() {
  const originalFetch = window.fetch;
  const originalXHR = window.XMLHttpRequest;
  let isProxyEnabled = true;

  window.addEventListener('proxySettingsUpdated', (event) => {
    isProxyEnabled = event.detail.isEnabled;
  });
  
  class ProxyInterceptor {
    static async sendProxyRequest(requestDetails) {
      return new Promise((resolve, reject) => {
        chrome.runtime.sendMessage(
          { type: 'proxy_request', request: requestDetails },
          response => {
            if (chrome.runtime.lastError) {
              reject(new Error(chrome.runtime.lastError.message));
            } else if (!response.success) {
              const error = new Error(response.error);
              error.status = response.status;
              error.details = response.details;
              reject(error);
            } else {
              resolve(response.response);
            }
          }
        );
      });
    }

    static createProxiedResponse(response) {
      const resInit = {
        status: response.status,
        statusText: response.statusText,
        headers: new Headers(response.headers)
      };

      const body = response.body ? new Uint8Array(response.body).buffer : null;
      return new Response(body, resInit);
    }
  }

  // Override fetch
  window.fetch = async function(input, init = {}) {
    if (!isProxyEnabled) {
      return originalFetch.apply(this, arguments);
    }

    try {
      const url = typeof input === 'string' ? input : input.url;
      const method = init.method || 'GET';
      
      const requestDetails = {
        method,
        url,
        headers: init.headers ? Object.fromEntries(new Headers(init.headers)) : {},
        body: init.body,
        origin: window.location.origin
      };

      const response = await ProxyInterceptor.sendProxyRequest(requestDetails);
      return ProxyInterceptor.createProxiedResponse(response);
    } catch (error) {
      console.warn('CORS Proxy Error:', error);
      return originalFetch.apply(this, arguments);
    }
  };

  // Override XMLHttpRequest
  function ProxiedXHR() {
    const xhr = new originalXHR();
    const proxiedXHR = Object.create(xhr);
    
    let requestMethod = '';
    let requestUrl = '';
    let requestHeaders = {};
    let isAsync = true;
    let failedWithProxy = false;
    
    proxiedXHR.open = function(method, url, async = true) {
      requestMethod = method;
      requestUrl = url;
      isAsync = async;
      if (!isProxyEnabled) {
        return xhr.open.apply(xhr, arguments);
      }
      // Don't call original open yet - wait for send
    };
    
    proxiedXHR.setRequestHeader = function(header, value) {
      requestHeaders[header] = value;
      if (!isProxyEnabled || failedWithProxy) {
        xhr.setRequestHeader.apply(xhr, arguments);
      }
    };
    
    proxiedXHR.send = function(body) {
      if (!isProxyEnabled) {
        return xhr.send.apply(xhr, arguments);
      }

      const requestDetails = {
        method: requestMethod,
        url: requestUrl,
        headers: requestHeaders,
        body: body,
        origin: window.location.origin
      };

      const handleResponse = (response) => {
        Object.defineProperties(proxiedXHR, {
          status: { value: response.status },
          statusText: { value: response.statusText },
          response: { value: new Uint8Array(response.body).buffer },
          responseText: { value: new TextDecoder().decode(new Uint8Array(response.body)) },
          readyState: { value: 4 }
        });

        // Set response headers
        proxiedXHR.getAllResponseHeaders = () => {
          return Object.entries(response.headers)
            .map(([key, value]) => `${key}: ${value}`)
            .join('\r\n');
        };

        proxiedXHR.getResponseHeader = (header) => {
          return response.headers[header] || null;
        };

        proxiedXHR.dispatchEvent(new Event('load'));
        proxiedXHR.dispatchEvent(new Event('readystatechange'));
      };

      const handleError = (error) => {
        failedWithProxy = true;
        console.warn('CORS Proxy Error:', error);
        // Fallback to original XHR
        xhr.open(requestMethod, requestUrl, isAsync);
        Object.entries(requestHeaders).forEach(([header, value]) => {
          xhr.setRequestHeader(header, value);
        });
        xhr.send(body);

        // Forward all events from original XHR
        ['load', 'error', 'timeout', 'abort', 'readystatechange'].forEach(event => {
          xhr.addEventListener(event, (e) => proxiedXHR.dispatchEvent(new Event(event)));
        });
      };

      if (isAsync) {
        ProxyInterceptor.sendProxyRequest(requestDetails)
          .then(handleResponse)
          .catch(handleError);
      } else {
        try {
          const response = await ProxyInterceptor.sendProxyRequest(requestDetails);
          handleResponse(response);
        } catch (error) {
          handleError(error);
        }
      }
    };

    // Forward other XHR properties and methods
    const properties = Object.getOwnPropertyNames(xhr);
    for (const prop of properties) {
      if (!(prop in proxiedXHR)) {
        const descriptor = Object.getOwnPropertyDescriptor(xhr, prop);
        Object.defineProperty(proxiedXHR, prop, descriptor);
      }
    }

    return proxiedXHR;
  }

  window.XMLHttpRequest = ProxiedXHR;
})();

---

// Manifest.json

{
  "manifest_version": 3,
  "name": "Enhanced CORS Bypass Proxy",
  "version": "1.4",
  "description": "A secure Chrome extension to bypass CORS restrictions with enhanced security and reliability",
  "permissions": [
    "scripting",
    "storage",
    "webRequest",
    "tabs"
  ],
  "host_permissions": [
    "<all_urls>"
  ],
  "background": {
    "service_worker": "background.js",
    "type": "module"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"],
      "run_at": "document_start",
      "all_frames": true
    }
  ],
  "web_accessible_resources": [
    {
      "resources": ["inject.js"],
      "matches": ["<all_urls>"]
    }
  ],
  "icons": {
    "16": "icons/icon16.png",
    "32": "icons/icon32.png",
    "128": "icons/icon128.png"
  },
  "action": {
    "default_icon": {
      "16": "icons/icon16.png",
      "32": "icons/icon32.png",
      "128": "icons/icon128.png"
    },
    "default_popup": "popup.html",
    "default_title": "Enhanced CORS Bypass Proxy"
  }
}

---

// Popup.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>CORS Bypass Settings</title>
  <style>
    body {
      width: 350px;
      padding: 15px;
      font-family: system-ui, -apple-system, sans-serif;
    }
    .container {
      display: flex;
      flex-direction: column;
      gap: 15px;
    }
    .switch {
      position: relative;
      display: inline-block;
      width: 50px;
      height: 24px;
    }
    .switch input {
      opacity: 0;
      width: 0;
      height: 0;
    }
    .slider {
      position: absolute;
      cursor: pointer;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: #ccc;
      transition: .4s;
      border-radius: 24px;
    }
    .slider:before {
      position: absolute;
      content: "";
      height: 16px;
      width: 16px;
      left: 4px;
      bottom: 4px;
      background-color: white;
      transition: .4s;
      border-radius: 50%;
    }
    input:checked + .slider {
      background-color: #2196F3;
    }
    input:checked + .slider:before {
      transform: translateX(26px);
    }
    .row {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
    .status {
      padding: 8px;
      border-radius: 4px;
      margin-top: 10px;
    }
    .status.active {
      background-color: #e8f5e9;
      color: #2e7d32;
    }
    .status.inactive {
      background-color: #ffebee;
      color: #c62828;
    }
    textarea {
      width: 100%;
      height: 80px;
      resize: vertical;
    }
    .error {
      color: #c62828;
      font-size: 12px;
      margin-top: 5px;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="row">
      <h3>CORS Bypass Proxy</h3>
      <label class="switch">
        <input type="checkbox" id="enableProxy">
        <span class="slider"></span>
      </label>
    </div>

    <div>
      <label>
        <input type="radio" name="mode" value="all" checked> Enable for all websites
      </label>
      <br>
      <label>
        <input type="radio" name="mode" value="custom"> Enable for specific websites
      </label>
    </div>

    <div id="customDomains" style="display: none;">
      <label>Allowed Domains (one per line):</label>
      <textarea id="domains" placeholder="example.com"></textarea>
    </div>

    <div>
      <label for="maxBodySize">Max Request Body Size (MB):</label>
      <input type="number" id="maxBodySize" min="1" max="50" value="10">
    </div>

    <div>
      <label for="timeout">Request Timeout (seconds):</label>
      <input type="number" id="timeout" min="5" max="60" value="30">
    </div>

    <div class="status" id="proxyStatus"></div>
    <div class="error" id="errorLog"></div>
  </div>
  <script> document.addEventListener('DOMContentLoaded', async () => {
  const settings = await chrome.storage.local.get([
    'proxyEnabled',
    'proxyMode',
    'allowedDomains',
    'maxBodySize',
    'timeout'
  ]);

  const enableProxy = document.getElementById('enableProxy');
  const modeInputs = document.getElementsByName('mode');
  const customDomains = document.getElementById('customDomains');
  const domains = document.getElementById('domains');
  const maxBodySize = document.getElementById('maxBodySize');
  const timeout = document.getElementById('timeout');
  const proxyStatus = document.getElementById('proxyStatus');
  const errorLog = document.getElementById('errorLog');

  // Initialize values
  enableProxy.checked = settings.proxyEnabled ?? true;
  maxBodySize.value = settings.maxBodySize ?? 10;
  timeout.value = settings.timeout ?? 30;
  
  for (const input of modeInputs) {
    if (input.value === (settings.proxyMode ?? 'all')) {
      input.checked = true;
    }
  }

  customDomains.style.display = settings.proxyMode === 'custom' ? 'block' : 'none';
  domains.value = (settings.allowedDomains ?? []).join('\n');

  updateStatus();

  // Event listeners
  enableProxy.addEventListener('change', async () => {
    await saveSettings();
    updateStatus();
    await updateIcon();
  });

  for (const input of modeInputs) {
    input.addEventListener('change', async () => {
      customDomains.style.display = input.value === 'custom' ? 'block' : 'none';
      await saveSettings();
    });
  }

  domains.addEventListener('change', saveSettings);
  maxBodySize.addEventListener('change', saveSettings);
  timeout.addEventListener('change', saveSettings);

  // Listen for status updates from background
  chrome.runtime.onMessage.addListener((message) => {
    if (message.type === 'proxyError') {
      errorLog.textContent = message.error;
      setTimeout(() => {
        errorLog.textContent = '';
      }, 5000);
    }
  });

  async function saveSettings() {
    const mode = document.querySelector('input[name="mode"]:checked').value;
    const domainList = domains.value
      .split('\n')
      .map(d => d.trim())
      .filter(d => d);

    await chrome.storage.local.set({
      proxyEnabled: enableProxy.checked,
      proxyMode: mode,
      allowedDomains: domainList,
      maxBodySize: parseInt(maxBodySize.value, 10),
      timeout: parseInt(timeout.value, 10)
    });

    await chrome.runtime.sendMessage({ type: 'settingsUpdated' });
  }

  function updateStatus() {
    proxyStatus.textContent = enableProxy.checked ? 'Proxy Active' : 'Proxy Inactive';
    proxyStatus.className = `status ${enableProxy.checked ? 'active' : 'inactive'}`;
  }

  async function updateIcon() {
    const icon = enableProxy.checked ? 'icon16.png' : 'icon16-disabled.png';
    await chrome.action.setIcon({
      path: {
        16: `icons/${icon}`,
        32: `icons/${icon.replace('16', '32')}`,
        128: `icons/${icon.replace('16', '128')}`
      }
    });
  }
});
</script>
</body>
</html>

---