Skip to main content
Every window created via overlay.windows.createWindow or overlay.windows.createInGameWindow is automatically hardened against malicious navigation — most notably ad creatives that attempt to take over the window or open unwanted sites. There is nothing to enable; this page describes the default policy and how to customize it.

Default Policy

Main-frame navigation

Top-frame navigation (will-navigate and main-frame redirects) is only permitted within allowed origins:
  • Your application’s own origin (the site URL configured in the Overlayed Dashboard)
  • The origin currently loaded in the window — so local dev servers and custom URLs keep working
  • Any hosts you list in allowedHosts
Anything else is blocked. A well-behaved SPA never navigates its top frame cross-origin, so a cross-origin top-frame navigation is treated as a takeover attempt. A blocked navigation is never forwarded to the system browser.
Sub-frame navigations are intentionally untouched, so ad iframes keep loading cross-origin creatives normally.
Redirects are only enforced for navigations initiated by the page itself. Calling loadURL with a URL that redirects (for example, a loading page handing off to your site) is trusted and unaffected.

New windows

window.open and target="_blank" links are handled per-URL: Opening unknown web URLs in the system browser preserves legitimate ad clickthroughs (advertiser domains are unpredictable) while making an in-app takeover impossible. Windows opened in-app are guarded by the same policy (plus the origin they were opened with), so the page that opened one can’t redirect or navigate it somewhere else.

User activation

Electron has no popup blocker. Unlike a browser, it lets any frame call window.open at any time, whether or not the user clicked anything, which is exactly what malvertising does to force a redirect. The guard makes up for it: an unknown web URL only opens in the system browser if the window received a click or key press in the last 5 seconds (Chromium’s own user activation lifespan), and each click opens at most one popup. Once something in the window tries to open a popup without user activation, clicks made during the next 10 seconds don’t open popups, even after those 10 seconds are up. That way the offending frame can’t ride the user’s next click somewhere else in the window.
Clicks inside cross-origin iframes (where most ad creatives render) are only visible to the guard on Electron 37 and later. On older versions, clicking such an ad does not open its landing page.

Tracking

Every blocked navigation and external open is logged with its URL and tracked via Cortex (navigation_blocked, window_open_external, window_open_denied), so a malicious creative can be identified and reported to the ad provider. window_open_denied includes a reason: no_user_activation and popup_cooldown point to a creative opening popups on its own.

Customizing the Policy

Configure the guard via the navigationGuard option of the overlayed function.

allowedHosts

Hosts the main frame may navigate to in addition to the defaults. Use this for legitimate top-frame cross-origin flows such as OAuth redirects. Matched against URL.host (hostname + port).

windowOpenHandler

Overrides the default window.open policy per-URL. Return "allow" (open in-app), "external" (open in the system browser, without requiring user activation), "deny" (block entirely), or undefined to fall back to the default policy.
Prefer windowOpenHandler over calling webContents.setWindowOpenHandler yourself. Electron only supports one handler per window, so the guard wraps yours instead of letting it replace the guard. Your handler only runs for windows the guard would open: your deny stands and your window options apply to allowed origins, but an allow for any other origin still goes through the guard’s policy. Set it after overlay.windows.createWindow returns: a handler set earlier (for example from app.on("web-contents-created")) is replaced when the window is registered.
As a safety net, "external" is only honored for http/https URLs — the guard never hands other schemes to the operating system, since that would launch whatever protocol handler is registered for them.