javascriptnode.jssecurityelectroncors

Do Electron apps enforce CORS restrictions in the renderer process?


I'm developing an Electron (v33.0.2) application and am struggling to understand how CORS is handled in the renderer process.

When making requests from the renderer process (not the main process), does Electron enforce CORS restrictions like a regular browser would? When I run my app locally (using vite) it consistently sends pre-flight requests with origin localhost:5173. I can see this in the developer tools network tab. However when I bundle and run my app (as a customer would run it in production), I do not see any pre-flight requests at all in the network tab. I've tested sending "complex" requests which should on paper be pre-flighted. I'm sure requests are being sent from the renderer process as the requests are being sent via React hooks (using fetch).

I've also noticed we have the nodeIntegration flag set on webPreferences which may have an impact here.

Would appreciate clarification on:

  1. Whether CORS is enforced in the Electron renderer process.
  2. Is CORS used on the file:// protocol? One difference between our dev and packaged app is that the origin in dev is http://localhost:5173, but the origin in the packaged app is file://.
  3. If setting nodeIntegration influences CORS behaviour.

Solution

  • I've worked with Electron apps quite a bit, and the way CORS behaves in the renderer process can definitely be confusing at first;

    1. Does Electron enforce CORS in the renderer process?

    Yes, in development, when your app runs on http://localhost:5173, the renderer process enforces browser-like CORS rules. That’s why you see preflight requests for "complex" requests (e.g., POST with custom headers).

    However, in production, Electron typically serves resources using the file:// protocol, which doesn’t have a traditional origin. Without an origin, CORS becomes irrelevant, so preflight requests disappear. This is expected behavior for apps moving from http:// to file://.

    2. Does CORS apply to the file:// protocol?

    No. The file:// protocol doesn’t enforce CORS because it lacks the concept of an origin (protocol + host + port). So, in production, requests made from file:// don’t trigger CORS checks or preflight requests. This might seem like CORS is “disabled,” but it’s just the nature of the protocol.

    3. Does nodeIntegration affect CORS?

    Yes, enabling nodeIntegration can bypass CORS entirely. With nodeIntegration: true, the renderer process gets access to Node.js APIs, which don’t enforce CORS restrictions. For example, using the Node.js http module or libraries like axios (configured to use Node.js) won’t trigger any CORS validation.

    That said, if you’re using fetch or XMLHttpRequest, browser-like behavior will still apply unless you explicitly bypass it with Node.js code.

    Why the difference between dev and production?

    The discrepancy you’re noticing comes from the origin (http://localhost:5173 in dev vs. file:// in production). This transition impacts CORS behavior because http:// origins follow web security policies, while file:// does not. It’s common for Electron apps to behave differently between these environments due to this.