Safeguard
Developer Tools•

Validating the sender of an Electron IPC message

Why Electron main process handlers should check who sent each IPC message, how to verify the frame origin, and what to do if a window loads other content.

Safeguard Security Team
3 min read

In Electron, check the sender of every privileged IPC message in the main process. Look at the frame that sent it and compare its origin to what you expect. Do not rely on the fact that your own window made the call, because frames inside that window may not be yours.

Why the sender matters

The main process holds the powerful APIs: files, shell, native menus, credentials. Renderers ask it to act through IPC. If a handler trusts any caller, then any frame that can reach the channel can trigger the action.

A window may contain more than your bundled page. An iframe, an embedded widget, a page the user navigated to, or injected content can all send messages if a bridge exposes the channel. The security guide lists sender validation among its recommendations for this reason.

Check the origin, not the URL string

With ipcMain.handle, the event carries senderFrame. The guide says to check the origin, not the full URL. Parse it with a URL parser. String prefix checks are easy to bypass, for instance with a host name that begins with your host name.

ipcMain.handle('read-config', (event) => {
  const origin = new URL(event.senderFrame.url).origin
  if (origin !== 'app://main') {
    throw new Error('Untrusted sender')
  }
  return loadConfig()
})

The app://main value above is an example for a custom protocol. Use whatever your app actually serves.

Combine it with other limits

Sender validation is one layer.

  • Serve the app from a custom protocol instead of file://, so the origin is meaningful. The guide notes that file:// pages can read any file on the machine.
  • Block navigation and new windows so the window cannot end up on a foreign origin.
  • Keep handlers narrow: one operation, validated arguments.
  • Return only what the caller needs.

Testing it

Write a test that sends the same message from a frame with a different origin and expects a refusal. If you cannot easily create such a frame, that is a hint that you have not thought about the case.

When your app does load remote content

Some apps must show a remote page. Give that window no preload bridge to privileged channels, or give it a separate, smaller bridge. Do not reuse the same preload for local and remote content.

Quick check

Is it enough to hide the channel name from the page?

No. A hidden name is not access control. Frames can discover or be handed names, and your handler cannot tell who called unless it checks the sender.

Should read only handlers be validated too?

Yes. A read can expose tokens, paths or user data. Apply the same check, then decide what each caller may see.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.