What’s electron ?, the design of electron desktop app, the story bug of the bug, the static code of the bug and how to find it, how to develop it and explain the code, explain how to discover it, mitigation, in this article we are going to discuss CVE i have found in 2022 and going through deep dive into the other methods to test your electron application.
The Story of Discovering This Bug
The story behind this vulnerability began during a routine bug-hunting session. While using Notable — a minimal, open-source note-taking app with over 23.1k stars on GitHub — to take notes on the target I was working on, something unexpected happened: XSS payloads started triggering inside the desktop application. That seemed unusual. A bit of digging revealed that Notable was built using Electron. This led to a deeper investigation into how a seemingly XSS could be escalated within the Electron environment, eventually revealing a path to Remote Code Execution (RCE).
What is Electron?
Electron is a framework for building desktop applications using JavaScript, HTML, and CSS. Embedding Chromium and Node.js into its binary Electron allows you to maintain one JavaScript codebase and create cross-platform apps that work on Windows, macOS, and Linux, like it can run in a desktop without writing native code, and was developed by github.
Understanding Electron Architecture

Main Process:
The Main Process is the heart of an Electron application. It runs Node.js and is responsible for managing the app’s lifecycle, including creating and controlling Render Processes (browser windows). It has full access to the operating system APIs and the file system and can execute arbitrary code.
Render Process (Chromium):
These are essentially Chromium browser windows responsible for rendering the UI. Each Render Process runs in isolation and handles a specific web page (typically one per window). By default, if Node.js integration is enabled, it also gains access to Node.js APIs, which can introduce critical vulnerabilities if untrusted content is executed.
IPC (Inter-Process Communication):
Electron uses IPC mechanisms to enable communication between Render Processes and the Main Process. This serves as a major security boundary. If the IPC channel is exposed or not properly validated, a malicious Render Process can exploit it to escalate privileges and achieve Remote Code Execution (RCE). This exact scenario was exploited in the Discord vulnerability [CVE number], which will be discussed in more detail in the upcoming sections.
Node.js and Native UI Layer:
Both the Main and Render Processes can interact with system-level features. The Node.js layer provides backend-like functionality while the Native UI layer handles platform-specific graphical interfaces.
Operating System:
The operating system acts as the foundation for the entire application. If an Electron app is compromised, an attacker may gain access to the system level, which is what makes Electron RCEs especially dangerous. Unlike web browsers like Chrome, Electron applications often lack the same level of sandboxing, making them more vulnerable if not properly secured.
The NodeIntegration misconfiguration
The chain of Cross-Site Scripting to RCE

Reproducing CVE-2020-15174 – Notable
it’s XSS but it’s in a Desktop but have more permissions because it’s based on the electron and have access to the node API directly so we can make a XSS payload to control the javascript code and then make a `child_process` and execute the calculator as a proof of the RCE (remote code execution) as shown in the following
As it was mentioned in the previous graph, the exploitation of this vulnerability was because of the nodeIntegration being set to true As shown in the picture:

which allows full access to the Node.js APIs.
In the notable source code at src/main/windows/window.ts, the nodeIntegration is set to true, which means, based on the above graph, the Electron library has integration access to Node.js, which in turn has access that can be abused to gain RCE in a malicious way
The exploitation was done by creating an .md file containing a Markdown line with the img tag as the XSS to trigger an error and confirm the action, which was opening the calculator in a child process:

Because it already has access to Node.js without sandboxing, we can use child_process to execute commands on the system and the calculator will pop up after the get opened in the notable app.

As we can see in the process monitor , Notable is running cmd`.`exe as a child process, which then spawns another cmd`.`exe instance to launch the Calculator

The Mitigation
By setting nodeIntegration: false, the renderer process no longer has direct access to Node.js APIs, preventing attackers from escalating XSS to arbitrary code execution and running remote commands on the system.
The Context Isolation and nodeIntegration misconfiguration
ContextIsolation is an Electron feature that allows developers to run code in the preload script and Electron APIs within a dedicated JavaScript context. This is important for security because it helps prevent websites from accessing Electron internals or the powerful APIs that the preload script can access.
The Exploitation Chain in VSCode
This vulnerability is a chained exploit leveraging a combination of flaws to achieve remote code execution (RCE). It starts with a Cross-Site Scripting (XSS) vulnerability in a webview, which is a web page rendered inside VS Code. The attacker uses a specially crafted file to inject malicious JavaScript into this webview.
The initial XSS provides the attacker with a limited foothold. To escalate privileges, the attacker exploits a second flaw: a misconfiguration in how VS Code handles local file access, specifically through the vscode-file:// protocol. The key weakness here is the lack of proper path validation or “sanitization,” which allows the attacker to use path traversal to break out of the intended directory and load an arbitrary, attacker-controlled file from the user’s system.
Because of additional misconfigurations, such as nodeIntegration being enabled and contextIsolation being disabled in some contexts, the loaded file can execute powerful Node.js APIs. This effectively bypasses the webview’s security sandbox, allowing the attacker to run system commands and achieve Remote Code Execution (RCE).
In short, the attack is a two-step process: an initial XSS to gain a foothold, followed by a path traversal to escalate privileges and ultimately run arbitrary code

The Visual Studio Code 1.63 was vulnerable to remote code execution through the chain of XSS and electron misconfiguration.
Reproducing CVE-2021-43908- Visual Studio Code
I’ve found exploit public in github link going to help us to reduce this vulnerability
Link : https://github.com/Sudistark/vscode-rce-electrovolt
So im going to explain the code of the exploit to get better understanding of how this exploitation is going
The poc directory was as the following

First XSS bypass the csp by using style
The first file, exploit.md, contained the code that sent a request to the stealID endpoint in order to leak the extension ID. When the file was opened and rendered using the vscode-webview:// protocol, the malicious CSS was executed and triggered the request and leak the ID.

The _gepCsp function was as below

The style-src ‘self’ ${rule} directive includes ‘unsafe-inline’, which means inline styles can be executed in the HTML. This was the root cause of the first XSS. However, it could not achieve remote code execution because the Content-Security-Policy was reset and sandboxed
Here the code of stealing the ID by it’s getting the uuid by split the origin header after / and print in the console middleware called and the second part of the code which is app.get(/stealID) for routing the request who reach stealID and call CreateHTML function.

As we see in the command line prints middleware called and the extensionID

CreateHTML function

The srcUrl → this is the URL that starts with vscode-webview://. It includes the extensionId and the publicUrl values that are needed to load the target webview.
But the Payload

This payload listens for postMessage events in the outer WebView, extracts the resource path, rewrites file:/// into a vscode-file://vscode-app/… path, replace exploit.md for RCE.html, and finally redirects (location.href) to the malicious file.
At the end, it also sends a fake reload message back to the extension using window.top.postMessage.
Second XSS: Abuse of postMessage in outer WebView This is where the second XSS happens: by abusing the postMessage channel, the attacker injects the malicious payload into the outer webview. Since the message was trusted and scripts were allowed, the payload gets executed, giving full control over the webview and enabling RCE
And for the htmlPoC here is the sendMessage to use payload and abuse the postMessage channel inside the outer WebView.
The iframe loads the vulnerable vscode-webview:// resource using srcUrl, and after 3 seconds the sendMessage() function automatically delivers the malicious payload with allowScripts:true. This tricks the webview into rendering attacker-controlled HTML/JS, even though scripts should normally be restricted.
And this is where the second XSS happens
the injected payload is executed because the outer webview trusts the postMessage without proper validation. From here, the attacker can chain it with the LFI to replace exploit.md and RCE.html and finally escalate into remote code execution (RCE)

RCE.html
It contained a script that used require with the child_process module to execute /System/Applications/Calculator.app on macOS or calc.exe on Windows, demonstrating how the vulnerability could be exploited to run arbitrary commands and

After combining both XSS (cross-site scripting) and LFI (local file inclusion), the exploit was able to bypass the CSP, load the malicious HTML file, and escape the sandbox. This allowed the attacker to escalate the bug into remote code execution
And now as we see the code is executed and we can execute the calc command

The Mitigation
VSCode tightened security by making Context Isolation enabled by default in Electron and disabling `nodeIntegration` (set to `false`). This means the renderer no longer gets raw access to Node.js APIs, cutting off one of the easiest paths to RCE.
But since the app still needs a way to interact with Node, they used **bridge isolation** with `contextBridge`. Think of it as a “controlled gate” — instead of giving the whole renderer access to powerful system APIs, developers expose only a few safe functions. The preload script defines what’s allowed, and everything else stays locked down.
This setup blocks direct system command execution from the renderer and forces attackers to go through a restricted channel. Basically, the RCE path is no longer wide open — it’s heavily filtered and much harder to exploit compared to the old setup
Conclusion
ElectronJS makes cross-platform development easier but requires careful attention to security. While it empowers developers to build feature-rich applications quickly, the same flexibility introduces critical risks if not handled responsibly. By disabling risky features such as nodeIntegration, enforcing contextIsolation, and strictly controlling IPC channels, developers can significantly reduce the attack surface and prevent XSS-to-RCE escalations that could compromise entire systems. The importance of these steps is reinforced by real-world incidents like CVE-2020-15174 and CVE-2021-43908, which clearly illustrate how insecure defaults can expose millions of users to serious vulnerabilities. Maintaining a proactive, security-first approach when developing with Electron is essential to protecting both applications and the users who rely on them.