VYPR
High severityNVD Advisory· Published Oct 6, 2020· Updated Aug 4, 2024

Unpreventable top-level navigation in Electron

CVE-2020-15174

Description

In Electron before versions 11.0.0-beta.1, 10.0.1, 9.3.0 or 8.5.1 the will-navigate event that apps use to prevent navigations to unexpected destinations as per our security recommendations can be bypassed when a sub-frame performs a top-frame navigation across sites. The issue is patched in versions 11.0.0-beta.1, 10.0.1, 9.3.0 or 8.5.1 As a workaround sandbox all your iframes using the sandbox attribute. This will prevent them creating top-frame navigations and is good practice anyway.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A bypass in Electron's will-navigate event lets cross-origin iframes initiate unpreventable top-frame navigations, undermining app security controls.

Vulnerability

Description CVE-2020-15174 is a security bypass in the Electron framework affecting versions before 11.0.0-beta.1, 10.0.1, 9.3.0, and 8.5.1 [1][4]. The will-navigate event is intended to allow applications to prevent unwanted navigations, a key security recommendation. However, when a sub-frame (e.g., an iframe) initiates a top-frame navigation to a different site, the event can be bypassed, allowing the navigation to proceed without being intercepted or blocked [1][4].

Exploitation

Method Exploitation requires the victim application to load an iframe from a cross-origin source. The attacker-controlled iframe can then perform a top-frame navigation (e.g., using target="_top" links) to any URL, bypassing the will-navigate event handler. No authentication or special network position is needed beyond the ability to serve content in an iframe [3][4]. The proof-of-concept in the patch commit demonstrates triggering this by having an iframe click a link that navigates the top frame [3].

Impact

If exploited, an attacker can redirect the entire Electron application window to a malicious site, potentially leading to phishing, data exfiltration, or further exploitation. This undermines the security model of applications that rely on will-navigate to enforce navigation restrictions [1][4]. The vulnerability affects all major Electron release lines prior to the patched versions.

Mitigation

The vulnerability is patched in Electron versions 11.0.0-beta.1, 10.0.1, 9.3.0, and 8.5.1 [1][4]. As a workaround, developers should sandbox all iframes using the sandbox attribute, which prevents them from creating top-frame navigations entirely [4]. Users are strongly advised to update their Electron dependency to the latest patched version.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
electronnpm
>= 8.0.0-beta.0, < 8.5.18.5.1
electronnpm
>= 9.0.0-beta.0, < 9.3.09.3.0
electronnpm
>= 10.0.0-beta.0, < 10.0.110.0.1

Affected products

2

Patches

1
18613925610b

refactor: wire will-navigate up to a navigation throttle instead of OpenURL (#25108)

https://github.com/electron/electronSamuel AttardAug 25, 2020via ghsa
4 files changed · +65 7
  • shell/browser/api/electron_api_web_contents.cc+0 6 modified
    @@ -743,12 +743,6 @@ content::WebContents* WebContents::OpenURLFromTab(
         return nullptr;
       }
     
    -  // Give user a chance to cancel navigation.
    -  if (Emit("will-navigate", params.url))
    -    return nullptr;
    -
    -  // Don't load the URL if the web contents was marked as destroyed from a
    -  // will-navigate event listener
       if (IsDestroyed())
         return nullptr;
     
    
  • shell/browser/electron_navigation_throttle.cc+24 0 modified
    @@ -19,6 +19,30 @@ const char* ElectronNavigationThrottle::GetNameForLogging() {
       return "ElectronNavigationThrottle";
     }
     
    +content::NavigationThrottle::ThrottleCheckResult
    +ElectronNavigationThrottle::WillStartRequest() {
    +  auto* handle = navigation_handle();
    +  auto* contents = handle->GetWebContents();
    +  if (!contents) {
    +    NOTREACHED();
    +    return PROCEED;
    +  }
    +
    +  v8::Isolate* isolate = v8::Isolate::GetCurrent();
    +  v8::HandleScope scope(isolate);
    +  auto api_contents = electron::api::WebContents::From(isolate, contents);
    +  if (api_contents.IsEmpty()) {
    +    // No need to emit any event if the WebContents is not available in JS.
    +    return PROCEED;
    +  }
    +
    +  if (handle->IsRendererInitiated() && handle->IsInMainFrame() &&
    +      api_contents->EmitNavigationEvent("will-navigate", handle)) {
    +    return CANCEL;
    +  }
    +  return PROCEED;
    +}
    +
     content::NavigationThrottle::ThrottleCheckResult
     ElectronNavigationThrottle::WillRedirectRequest() {
       auto* handle = navigation_handle();
    
  • shell/browser/electron_navigation_throttle.h+2 0 modified
    @@ -14,6 +14,8 @@ class ElectronNavigationThrottle : public content::NavigationThrottle {
       explicit ElectronNavigationThrottle(content::NavigationHandle* handle);
       ~ElectronNavigationThrottle() override;
     
    +  ElectronNavigationThrottle::ThrottleCheckResult WillStartRequest() override;
    +
       ElectronNavigationThrottle::ThrottleCheckResult WillRedirectRequest()
           override;
     
    
  • spec-main/api-browser-window-spec.ts+39 1 modified
    @@ -442,7 +442,13 @@ describe('BrowserWindow module', () => {
             let server = null as unknown as http.Server;
             let url = null as unknown as string;
             before((done) => {
    -          server = http.createServer((req, res) => { res.end(''); });
    +          server = http.createServer((req, res) => {
    +            if (req.url === '/navigate-top') {
    +              res.end('<a target=_top href="/">navigate _top</a>');
    +            } else {
    +              res.end('');
    +            }
    +          });
               server.listen(0, '127.0.0.1', () => {
                 url = `http://127.0.0.1:${(server.address() as AddressInfo).port}/`;
                 done();
    @@ -506,6 +512,38 @@ describe('BrowserWindow module', () => {
               expect(navigatedTo).to.equal(url);
               expect(w.webContents.getURL()).to.equal('about:blank');
             });
    +
    +        it('is triggered when a cross-origin iframe navigates _top', async () => {
    +          await w.loadURL(`data:text/html,<iframe src="http://127.0.0.1:${(server.address() as AddressInfo).port}/navigate-top"></iframe>`);
    +          await delay(1000);
    +          w.webContents.debugger.attach('1.1');
    +          const targets = await w.webContents.debugger.sendCommand('Target.getTargets');
    +          const iframeTarget = targets.targetInfos.find((t: any) => t.type === 'iframe');
    +          const { sessionId } = await w.webContents.debugger.sendCommand('Target.attachToTarget', {
    +            targetId: iframeTarget.targetId,
    +            flatten: true
    +          });
    +          await w.webContents.debugger.sendCommand('Input.dispatchMouseEvent', {
    +            type: 'mousePressed',
    +            x: 10,
    +            y: 10,
    +            clickCount: 1,
    +            button: 'left'
    +          }, sessionId);
    +          await w.webContents.debugger.sendCommand('Input.dispatchMouseEvent', {
    +            type: 'mouseReleased',
    +            x: 10,
    +            y: 10,
    +            clickCount: 1,
    +            button: 'left'
    +          }, sessionId);
    +          let willNavigateEmitted = false;
    +          w.webContents.on('will-navigate', () => {
    +            willNavigateEmitted = true;
    +          });
    +          await emittedOnce(w.webContents, 'did-navigate');
    +          expect(willNavigateEmitted).to.be.true();
    +        });
           });
     
           describe('will-redirect event', () => {
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.