ConceptioArchivearXiv CS
arXiv CSopen access

Buzz to Boom: Detecting Message Progression Vulnerabilities in Electron Applications via Segmented Directed Fuzzing

Unknown · 2026 · arxiv_cs
arXiv CS · Papers · License: Open Access · 2026
Open Source ↗Direct PDF ↓
cryptography, security, privacy, cybersecurity

Buzz to Boom: Detecting Message Progression Vulnerabilities in Electron Applications via Segmented Directed Fuzzing Jianjia Yu, Zhengyu Liu, Ziyang Li, Yu Sun, and Yinzhi Cao {jyu122, zliu192, ziyang, ysun227, yinzhi.cao}@jhu.edu Johns Hopkins University

arXiv:2607.20698v1 [cs.CR] 22 Jul 2026

Abstract Electron is a popular framework for building cross-platform desktop applications using web technologies. Such applications consist of multiple processes with different privilege levels that communicate via message passing. When interprocess messages carry attacker-controlled inputs, they can propagate across processes and reach privileged APIs, e.g., command execution. Such a message propagation behavior is characterized as Message Progression Vulnerabilities (MPVs). The exploitation of MPVs is challenging because it often requires multiple steps, e.g., first arbitrary code execution in one process via message passing, and then command injection in another process using another message crafted in the first process. To our knowledge, existing works on Electron security only study unsafe configurations and malicious Document Object Model (DOM) content, i.e., they cannot detect or exploit these vulnerabilities that need to be triggered by complex cross-process exploits via message passing. We present Proton, a segmented directed fuzzing framework for detecting MPVs. Our key insight is to decompose end-to-end fuzzing into per-process segments along messagepassing boundaries, where the goals of fuzzing each segment are either: (i) reaching a sink in the current process or (ii) propagating the payload to the next process, to enable the exploration of another process. In the second case, the messages seed the corpus of the next segment. Finally, Proton synthesizes crash inputs from each process to validate end-to-end exploits. We evaluate Proton against 589 real-world Electron applications, resulting in 23 zero-day MPVs. Among them, 22 lead to OS command execution, including projects with over 50k GitHub stars. We responsibly disclosed all findings. To date, we have received 13 acknowledgments, 11 fixes, and 11 CVEs, including a bug bounty from Vercel.

1

Introduction

Electron is a widely adopted framework for building crossplatform desktop applications using web technologies, powering popular applications such as Visual Studio Code, Slack,

and Discord. Electron applications consist of browser-like renderer processes and a privileged Node.js-enabled main process that can access local files, spawn processes, and directly execute OS commands. These processes communicate through message-passing interfaces, e.g., Inter-Process Communication (IPC), as well as other cross-process operations including script execution, window navigation, and custom protocol handlers. When such cross-process channels carry attacker-controlled inputs, those inputs can progressively propagate across processes and reach privileged APIs, e.g., command execution. We characterize such crossprocess propagation of attacker-controlled data as Message Progression Vulnerabilities (MPV S). A noteworthy property of a Message Progression Vulnerability—differentiating it from existing ones [1, 2]—is the involvement of multiple Electron processes, leading to chaining two or more vulnerabilities through multi-step message passing, to the final consequence. Here is a three-step example. First, the message starts with a custom URI click in an external browser, and is then passed to the Electron main process for a client-side request forgery. Second, the message progresses from the main process to the render in Electron applications to exploit an arbitrary code execution vulnerability in the render. This still is not enough, though, because the render process is isolated without access to privileged APIs. Therefore, lastly, another message progression from the render back to the main process is needed to exploit another command injection vulnerability in the main. The chaining of these three vulnerabilities consists of a Message Progression Vulnerability, whereas prior message-related vulnerabilities [1–5] only need at most one-step exploitation from one process to another. Due to this property, the end-to-end detection and exploitation of MPV are challenging, and none of the prior works can achieve them. First, existing Electron security studies mainly focus on unsafe configuration checks [6–8] and mitigation of malicious Document Object Model (DOM) content [9, 10], or unsafe cross-context communication [11]. None of them detects the progression of attacker-controlled messages across

2. 3.

Remote Server

Local file Remote server

3.

(request) {

Chrome

Chrome

Chrome https://gitlab.com/mal/repo

https://gitlab.com Open Paperlib?

Features: - Please click on this link

Features: Cancel - Please click onOpen this link

User

Remote resource download

https://gitlab.com/ wants to open this app.

A

Features: - Please click on this link

Host a malicious (second loading)

1

Embeds a malicious link on a site

2

B Custom URI Handled by an Electron app

paperlib://embed/badurl

// main.ts (Main Process) app.on('open-url', (event, uri) => { const { host, pathname} = new URL(uri); utilityPort.postMessage({ channel: host, url: pathname }); });

Chrome

https://gitlab.com/malicious/r Paperlib epo

Paperlib https://gitlab.com/malicious/repo

Welcome to paperlib! Authors: xxx DOI: xxx Features: - Please click on this link

Calculator.app <script>xxx Authors:xxx DOI: xxx Features: - Please click on this link

🤡 1337

AC

C

Client-side Request Forgery // utility.ts (Utility Process) port.onmessage = msg => { const text = await (await fetch(msg.data.url)).text(); rendererPort.postMessage({ content: text });}

D

%

÷

Arbitrary command execution <!-- view.vue (Renderer Process) --> port.onmessage = msg => { slot.push({content: msg.data.content}); }; <div v-html="item.content"></div>

Figure 1: An illustration of a zero-day MPV found by Proton in Paperlib: a victim clicks on a malicious custom URI link ➀ embedded in a webpage, which launches Paperlib after browser confirmation ➁. The URI payload progresses across three Electron processes, main (B), utility (C), and renderer (D), via message passing, ultimately yielding arbitrary command execution.

contents.on('will-navigate',(e, url) => { if (isInternalUrl(url)) { return; } e.preventDefault(); shell.openExternal(url)...; });

multiple Electron processes, let alone MPV. Second, it is challenging to adapt existing techniques to detect MPV as oxy?hidden=1&redirect_uri=file://google.com//System/Applications/Calculator.app/Contents/ well. On the one hand, cross-context static analyses [1, 2] can MacOS/Calculator identify suspicious message handlers or privileged API uses, Sending request AFFiNE launches Local RCE ii but they struggle with the dynamic message construction and asynchronous message passing, which makes it difficult to determine whether a flagged path can be a feasible cross-process exploit chainElectron or synthesize an exploit. ert app Renderer Process On the other hand, existing dynamic techniques such as web fuzzing [12–14] are monolithic and do not coordinate across Electron’s process boundaries. More specifically, inputs at each boundary are constrained by what survives the preceding boundary, i.e., existing fuzzers often waste their budget on inputs that fail to propagate past the first boundary. In this paper, we present Proton, a segmented directed fuzzing framework for detecting and exploiting Message Progression Vulnerabilities in Electron applications. The key insight of Proton is to decompose the end-to-end fuzzing— potentially spanning over multiple processes—into independent segments along message-passing boundaries, to efficiently explore deeper program states. More specifically, the fuzzing segmentation has two phases. Phase I performs static progression analysis to identify candidate vulnerable paths and segment boundaries by reasoning about payload injection points, IPC message flows, and dangerous API sinks. Then, Phase II performs coverage-guided fuzzing on each segment independently. There are two objectives: reaching a security-related, terminal sink in the current process, or reaching an intermediate sink, or so-called Progression API that propagates the payload through messaging to another process. When a fuzzing process on one segment successfully reaches a Progression API, the message it produces becomes the corpus for the next segment. Proton will then mutate the message content driven by a harness generated by Large Language Models (LLMs) to fuzz the next segment. After all per-segment fuzzing, Proton synthesizes end-to-end exploits and validates them against the whole application. We evaluate Proton on 589 real-world Electron applications and discover 23 previously unknown vulnerabilities,

including 22 that can be escalated to full RCE. The vulnerable applications include highly popular projects with over 50k arbitrary command through DOM XSS C Executesdisclosed GitHub stars. We responsibly all findings, receiv<div v-html="item.content"></div> ing 13 acknowledgments, 11 fixes, and 11 CVE identifiers to date, including a bug bounty from Vercel for a vulnerability in Hyper. Compared to end-to-end fuzzing, Proton discovers C Executes arbitrary command 17 more zero-day vulnerabilities. this.pty = spawn(shell, args, opts); if (this.pty) {

this.pty.write(data); Contributions. This paper }makes three main contributions: else { /* ... */ } }

• We characterize Message Progression Vulnerabilities (MPV S) in Electron applications, where attacker-controlled inputs propagate across multiple processes via message passing, chaining two or more vulnerabilities through multistep exploitation to ultimately reach privileged APIs such as command execution. • We propose segmented directed fuzzing as a detection strategy for MPV S and realize it in Proton, a framework that decomposes multi-process exploit chains into segments at message-passing boundaries and fuzzes each segment toward either a local sink or a downstream-bound message. • We evaluate Proton on 589 real-world Electron applications, uncovering 23 zero-day MPV S, with 22 RCE exploits, and received 11 CVEs with 11 fixes and 13 acknowledgments, along with a bug bounty from Vercel. We open-source Proton to support future research.

2

Message Progression Vulnerability

In this section, we begin with the description of Message Progression Vulnerability in §2.1. Then, we present a systematization of Message Progression Vulnerabilities in §2.2, including Electron’s process model and execution contexts ( §2.2.1), the payload sources ( §2.2.2), and sinks ( §2.2.3). Finally, §2.3 illustrates the threat model.

2.1

Vulnerability Description

Figure 1 illustrates a zero-day MPV in Paperlib: a victim clicks a malicious paperlib:// URI embedded in a webpage

(box A), which triggers a chain of three vulnerabilities across Electron’s processes via message passing — an unintended function invocation in the main process (box B), a client-side request forgery in the utility process (box C), and DOM-based XSS in the renderer (box D) — ultimately yielding arbitrary command execution. This four-step chain, spanning three Electron processes, is a MPV. The chaining of vulnerabilities through message progression turns a browser click into full RCE. We present the vulnerability in detail in Section 3.1. To MPV generalize beyond this example, we next describe the process model and execution context of Electron applications, and then systematize MPV’s sources and sinks.

2.2

Vulnerability Systematization

2.2.1

Process Model and Execution Context

Electron employs a multi-process architecture consisting of a privileged main process and multiple utility and renderer processes. The main process runs in Node.js with full native API access, controlling the application lifecycle. Utility processes are spawned by the main to handle background tasks such as network requests and file access, and also run with Node.js access. Renderer processes display web content and interact with users. Furthermore, to facilitate communication with the main process, Electron provides a group of privileged APIs through preload scripts configured per window. Under the default secure configuration, each renderer maintains two isolated JavaScript contexts: (1) the preload context executes with access to privileged APIs (e.g., process and ipcRenderer) and selectively exposes functionality to web content via contextBridge; (2) the main world context executes web page code with access only to standard browser APIs and the APIs exposed by preload scripts. This isolation prevents web content from directly accessing privileged APIs while enabling main-process services via IPC. The different processes and execution contexts with distinct privilege levels define the boundaries across which message progression happens, and determine which inputs can be potential payload sources and whether an API is a progression API or a terminal sink. We next categorize sources and sinks along these dimensions in §2.2.2 and §2.2.3. 2.2.2

Sources

Attacker-controlled payloads that originate outside the application’s trust boundary can enter an Electron application via OS-level handlers or application logic. We identify three such source types, as shown in Table 1. • Custom URI (U). The attacker embeds a malicious payload within a URI using the application’s registered custom scheme, e.g., app://action?content=payload. When a victim clicks the link in a browser, such as Chrome, the OS invokes the Electron application and delivers the URI to its

open-url handler, where attacker-controlled parameters enter the application and may propagate to downstream sinks via IPC and other message progression channels. • Remote Server Response (S). The application fetches content from an attacker-controlled server when attackercontrolled values flow to network APIs such as fetch. In MPV chains, this source commonly arises when an intermediate vulnerability, such as a client-side request forgery (CSRF), happens. For example, the initial custom URI app://install?url=evil.com causes the application to fetch and process attacker-controlled content from evil.com through CSRF, and the server response is further processed. This pattern commonly appears in applications supporting plugin installation, remote file loading, and MCP server imports. • Local File Access (F). The application loads content from the local file system at an attacker-specified path, when attacker-controlled values flow to file system APIs (e.g., fs.readFile) or BrowserWindow methods (e.g., win.loadFile). No prior file system compromise is required: an attacker can exploit browser auto-download to silently place a malicious file in the default downloads directory, then trigger a custom URI to cause the application to load it, e.g., app://open?path=~/Downloads/evil.js. 2.2.3

Sinks

In Table 1, we list the MPV sinks across Electron’s multiple processes and execution contexts. We distinguish them by their effects: intermediate sinks forward attacker-controlled data into a message destined for another process; terminal sinks directly cause the security consequence (e.g., OS command execution). Note that some APIs act as either intermediate or terminal sinks depending on the process and the execution context — e.g., whether it has Node.js access, as listed at lines 3-7. In the following paragraphs, we classify each sink by its primary role and note conditional behavior where applicable. Intermediate Sinks. Intermediate sinks are the APIs that forward attacker-controlled content to another process, toward a terminal sink. They define the segment boundaries at which Proton decomposes exploit chains for per-segment fuzzing, and also serve as one of the two subjects of segment fuzzing. Specifically, we identify two types of intermediate sinks, the IPC-related APIs and the window navigation/embedding APIs. First, IPC communications. These are the most prevalent intermediate sink in our dataset. The most common patterns are ipcRenderer.send(C, Msg) and port. postMessage(Msg), where C is the channel field that routes the message, and Msg is the content field. A summary of all types of IPC communication mechanisms in Electron applications can be found in Table 8 in the Appendix.

Table 1: Categorization of Message Progression Vulnerability sinks across Electron’s multi-process architecture. We distinguish them by their effects: intermediate sinks (↗) forward attacker-controlled data into a message destined for another process; terminal sinks (□) directly cause the security consequence (e.g., OS command execution); a single API may act as either depending on the runtime context (↗ / □). For each sink type, we show: its effect, its availability across processes and execution contexts, potential payload sources, vulnerable code patterns, and exploitation conditions, where T denotes tainted data. API Location Payload (U/F/S)

Code Patterns

Conditions

Inter-Process Communication ↗

U/F/S

ipcRenderer.send(C, T) port.postMessage(T)

T contains attack-controlled payload

Remote Source Fetching

U/F/S

fetch(T) https.get(T)

T contains attack-controlled payload

Window Navigation

↗/□

U/(F)2 /(S)3 U/F U/(F)2 /S

win.loadURL(T) contents.loadFile(T) window.location.href=T

T is URL pointing to attacker-controlled resource T is path pointing to attacker-controlled local file T is URL pointing to attacker-controlled resource

Subview Embedding

↗/□

U/(F)2 /S

iframe.src=T; webview.src=T

T is URL pointing to attacker-controlled resource

U U

contents.executeJavaScript(T) webFrame.executeJavaScript(T)

T contains attacker-controlled JavaScript code T contains attacker-controlled JavaScript code

U

element.innerHTML=T

T contains attacker-controlled HTML/JS code

U

new Function(T); eval(T)

T contains attacker-controlled JS code

U

exec(T); spawn(T, {shell:true}) T contains attacker-controlled shell commands

Description

Effect

Window Script Execution

↗/□

DOM-based Script Exec.

↗/□

Code Execution

↗/□

Command Execution

Module Loading

External Open Service

File System Write

Main Util. Renderer Proc. Proc. Proc. Preload Main

#

# # #

# #

#

# #

#

#

#

#

#

# #

# #

# #

# G

# G

G # # G

G # # G

# G

# G

# G

U/(F)1

require(T); import(T)

T is path to attacker-controlled local JS file

U/S U/F

shell.openExternal(T) shell.openPath(T)

T is URL to attacker-controlled resource T is path to attacker-controlled local file

# G

U

fs.writeFile(T1 , T2 )

T1 (path) and T2 (content) are attacker-controlled

Effect: ↗: Intermediate sink, □: Terminal sink; API Location: : Sink available under default secure configuration (nodeIntegration=false, contextIsolation=true, and sandbox=true); # G: Sink available under insecure configuration (nodeIntegration=true, contextIsolation=false, or sandbox=false); #: Sink not available under any configuration. Payload: U=Custom URI, S=Remote Server Response, F=Local File Access; parentheses indicate optional. 1 : Local file not necessary for import as it supports data: protocol. 2 : File protocol may be necessary to bypass CSP. 3 : Remote server not necessary when T uses javascript: or data: protocol.

Second, navigation and embedding APIs. These cause a process to load new content into an execution context, implicitly forwarding attacker-controlled URLs or paths, such as win.loadURL(T) and iframe.src=T. These APIs act as intermediate sinks when the loaded content introduces further sinks in a new execution context. They become terminal when the loaded resource directly causes a security consequence. For example, when T starts with javascript:, so the code is directly executed, or T is a file:// path to a local HTML file and Node is enabled, in which case the file can embed JavaScript code calling Node APIs. Terminal Sinks Terminal sinks directly cause the final security consequence without further message progression, including OS command execution, module loading, and external service invocation. Beyond direct code execution sinks, we also consider arbitrary file write operations, as they can be readily escalated to code execution by overwriting application source code or system configuration files (e.g., .bashrc and desktop autostart entries) that execute during application or system startup. The one type that is conditionally terminal are the code execution APIs, as shown in lines 4-6 in Table 1. APIs such

as contents.executeJavaScript(T) and eval(T) evaluate attacker-controlled JavaScript. When reached in a process with Node.js access, i.e., main, utility, or a renderer with Node enabled, these APIs yield remote code execution directly and act as terminal sinks. When reached in a sandboxed renderer without Node.js access, they instead act as intermediate sinks. The attacker uses the gained JavaScript execution to invoke IPC APIs exposed via the preload script, progressing the payload to a privileged process where a terminal sink can be reached.

2.3

Threat Model

We consider an end user with a vulnerable Electron desktop application that has registered a custom URI scheme with the OS. Unlike prior works [7, 9–11] that assume attackers already control renderer content, we consider a remote web attacker operating entirely outside the application, who can publish or embed crafted URIs on third-party sites or their own webpage without injecting content into the app directly. When the victim clicks a crafted link or visits an attackercontrolled page in a standalone browser, the OS invokes the target Electron application to handle the URI, leading to arbi-

paperlib://PLAPI.commandServ ice.run?args=["import-from", "https://evil.com/poc.html"] app.on("open-url", (event, uri) => { const { protocol, hostname, search } = new URL(uri); Segment A const [api, service, method] = hostname.split("."); Input: uri const params = new URLSearchParams(search); Output: api, service, method, args const args = JSON.parse(params.get("args") || "[]"); global[api][service][method](args); });

Fuzzing Harness

main.ts (Main Process)

1 2 3 4 5 6 7 8 global.PLAPI.commandService.run = function(args){ utilityPort.postMessage(args); }; 9

entation nalysis

Unintended Function Invocation

Segment B Input: api, service, method, args Output: args

Segment C

CSRF

Input: fetch(…) Output: msg

paper-detail-view.vue (Renderer Process) port.onmessage = msg => { slot1.push({ content: msg.data.content }); }; <Section /* Vue Template */ v-for="(item, index) in slot1" :id="`detailspanel-slot1-${index}`" :title="item.title"> <div v-html="item.content"></div> </Section>

function reconstruct_input_A(buf) { let [ api, serv, method, args ] = buf; let url = new URL( `${PROT}://${api}.${serv}.${method}`); url.searchParams.set("args", JSON.stringify(args)); return url.toString(); }

main.ts:2 function harness_C(buf){ const fn = utilityMethods[buf1]; fn(...buf2); } // ...remove original lines 2-4

Input: msg

1 2 3 4 5 6 7 8

Canary

main-entry.ts:6 function harness_B(buf){ global[buf1][buf2][buf3](buf4); } // ...remove original line 6

util.ts (Utility Process) 1 port.onmessage = msg => { Output: webUrl 2 const [methodName, ...methodArgs] = msg.data; 3 const fn = utilityMethods[methodName]; <img src=1 4 fn(...methodArgs); }; onerror="require('child_pro 5 const utilityMethods = { cess').spawn('open',['-a',' 6 "import-from": async (webUrl) => { Calculator'])"> 7 const text = await (await fetch(webUrl)).text(); 8 rendererPort.postMessage({ content: text }); Segment D 9 }, ... };

Input Reconstructor

main.ts:7 function harness_D(buf){ rendererPort.postMessage({ content: buf }); } // ...remove original lines 7-8 paper…view.ts:2

function harness_E(buf){ slot1.push({ content: buf }); } // ...remove original line 2

Segment E Input: msg

DOM XSS

hook(Element.prototype, 'innerHTML', { set: function (this, args, setter) { let html = args[0]; checkForCanary(html); }});

Figure 2: Exploitable control-flow path in Paperlib [15] discovered by Proton: code snippets (left) from files running in the main, utility, and renderer processes; agentic analysis segments the control flow into five segments A–E (middle); LLM-synthesized artifacts on the right include an input reconstructor (A), fuzzing harnesses (B–E), and runtime canaries for final exploit validation (E). trary command execution. We assume the application need not be already running, as the protocol is pre-registered with the OS, and no further user interaction is required.

3

Overview

We start with a motivating example in Section §3.1, then describe the key detection challenges and present an overview of our segmented fuzzing solution in Section §3.2.

3.1

A Motivating Example

Figure 2 presents a real-world zero-day Message Progression Vulnerability (CVE-2025-XXXX) that leads to remote code execution, discovered by Proton in Paperlib [15], a popular open-source reference management system. The vulnerability lies in its core functionality that is designed to enable import of reference lists from external resources via paperlib:// URI scheme. The exploit requires chaining several vulnerabilities. By crafting a malicious URI, an attacker first causes an

unintended privileged function invocation, which then leads to a client-side request forgery (CSRF), triggering the application to fetch attacker-controlled content. Finally, when the content is processed, the payload exploits a DOM cross-site scripting to achieve arbitrary OS command execution. We have responsibly disclosed this vulnerability to the developers, who have acknowledged and patched it. Vulnerability Details. The application registers a custom URI handler for Electron’s open-url event in the main process (main.ts, line 1). When a user clicks a malicious URI, the handler parses the URI into components (line 2) using new URL, extracts the API path by splitting the hostname (line 3), and retrieves arguments from the query parameters (lines 4-5). The handler then uses bracket notation to dynamically resolve and invoke the specified method on the global object (line 6), which is not expected to be accessible from custom URIs — constituting an unintended function invocation. In this case, the attacker’s URI invokes global[api] [service][method](args) with malicious arguments. The resolved method commandService.run (line 8) forwards

these attacker-controlled arguments to the utility process via postMessage (line 9). Next, the utility process (util.ts) receives the message through its onmessage handler and destructures the method name and arguments (lines 1-2), resolves the corresponding function from the utilityMethods object, and invokes it (line 3-4). The import-from method (lines 5-9) receives the malicious URL as its argument, fetches content from the attacker-controlled server using fetch (line 7)— a client-side request forgery that introduces an additional remote server response payload (Source S). The utility process then forwards the fetched text to the renderer process via postMessage. Finally, the renderer process (paper-detail-view.vue) receives the fetched content through onmessage (line 1) and pushes it into the slot1 array (line 2). The Vue template (lines 3-7) then iterates over slot1 and renders each item’s content using the v-html directive (line 7), interpreting the content as raw HTML and executes any embedded JavaScript, constituting a DOM-based XSS sink. Exploitation. Since the renderer process is configured with node integration enabled and context isolation disabled, JavaScript executed in the renderer gains direct access to Node.js APIs. To host Source S, we publish a malicious PDF on a public file hosting service. In our proof-ofconcept, the injected script achieves arbitrary command execution via require(’child_process’).spawn(), launching Calculator.app on the victim’s machine.

3.2

Challenges and Our Solutions

The key challenge in detecting MPV S lies in their chained nature: exploit chains span multiple processes and sources via message progression, where several vulnerabilities compose into a severe consequence. Using the Paperlib example in Figure 2, we describe three concrete detection challenges this poses, and present how Proton addresses them through segmented fuzzing. Challenge I: Multiple payload sources. Detecting Message Progression Vulnerability requires generating inputs from multiple heterogeneous sources that are introduced at different points in the execution flow. In the motivating example, detecting the vulnerability in Paperlib requires generating two separate payloads introduced at different places: the custom URI (Source U) processed by the main process, and the remote server content (Source S) fetched by the utility process. Furthermore, S depends causally on U. The URI determines which utility method executes, which then fetches the malicious content from the attacker’s server. Traditional fuzzing cannot efficiently handle this because it operates with a single input source at program entry. It has no mechanism to discover S, which only appears after U reaches fetch(), nor to fuzz each source independently rather than exploring their cross-product.

Challenge II: Customized and complex parsing. Beyond multiple sources, each input must satisfy application-specific parsing constraints that vary across applications. In Paperlib, the URI hostname is split into three components (main process, line 3) that resolve to a valid method path like global["PLAPI"]["commandService"]["run"] (line 6). The args parameter must be valid JSON (line 5) with the correct method name as the first array element to trigger the fetch operation (utility process, line 7). The server response must be valid HTML text containing JavaScript that exploits the v-html sink (renderer process, line 7). Traditional fuzzing cannot efficiently generate such inputs due to the sparse valid input space, while symbolic execution struggles to model complex parsing operations like JSON and URL parsing. Challenge III: Cross-process Execution Overhead. The multi-process architecture of Electron makes deep state exploration prohibitively expensive due to multiplicative crossprocess execution overhead. In the Paperlib example, exploring different states in the renderer process (lines 3-7 in paper-detail-view.vue) requires repeatedly executing the entire cross-process chain starting from the main process through the utility process. As chains grow longer across more processes, this multiplicative cost drastically reduces fuzzing throughput, limiting the ability to explore and generate inputs for deep program states where vulnerabilities may reside. Our Solutions. Proton addresses all three challenges through segmented fuzzing, that is, decomposing the complete exploitable control-flow path at Progression APIs and invertible parsing operations, then fuzzing each segment separately. As shown in Figure 2, Proton first performs agentic static analysis to identify a candidate vulnerable path and its segment boundaries, then generates fuzzing harnesses (B–E) and an input reconstructor (A) for each segment. It then conducts segmented fuzzing to verify their reachability and generate end-to-end proof-of-concept inputs. We now explain how this addresses each challenge. First, Proton defines operations where attacker-controlled input crosses into a new execution surface as Progression APIs, and segments the exploit path at these boundaries. In the Paperlib example, fetch() is a Progression API, as it receives the attacker-controlled URL from Source U and forwards it to an external server whose response becomes Source S. By segmenting at fetch(), Proton fuzzes the upstream segment to discover whether the attacker can control the request URL, then focuses on fuzzing the downstream segment over the server response independently. Second, Proton handles complex parsing operations by leveraging their invertibility. Operations like JSON.parse() and new URL() have the property that given any valid output, a corresponding input can be reconstructed. Proton exploits this through the input reconstructor (Segment A in Figure 2): instead of generating raw URI strings that mostly fail parsing,

the reconstructor works backward from valid parsed outputs to produce well-formed inputs that satisfy parsing constraints directly. Third, Proton fuzzes each segment separately with persegment harnesses, each of which initializes the segment’s execution state directly without replaying preceding segments. For instance, harness E fuzzes content directly, bypassing main process URI parsing, utility process fetch, and all IPC communication, allowing Proton to explore the renderer at native fuzzing speed rather than replaying the entire chain per iteration. Once a valid segment chain is found, Proton sythinsizes the complete payload and validates end-to-end exploitability against the whole application.

are either a Progression API, which seeds the next segment’s corpus with its output, or a sink that directly manifests the vulnerability.

4

Complexity of an End-to-End Fuzzing Campaign. We characterize the cost of a fuzzing campaign by the size of its program state space, which we upper-bound by the product of: (i) the size of the input space |I| under exploration and (ii) the maximum number of executed instructions N along the path (assuming no infinite loops, since such paths are non-exploitable and cannot be fuzzed). In the worst case, a monolithic, or traditional end-to-end fuzzer must explore all |I| possible inputs and execute up to N instructions for each, yielding a complexity of O(|I| · N) for validating the exploitability of a candidate path π.

Methodology

Proton employs a two-phase methodology to efficiently uncover MPV S in Electron applications. First, an agentic static analysis phase identifies source–sink paths and segmentation boundaries, and generates per-segment harnesses. Second, a segmented fuzzing phase exercises each segment independently using generated harnesses. Finally, Proton performs end-to-end validation to compose the segment-level inputs into a full exploit payload and validates the path. We begin with a complexity analysis (§4.1), then describe agentic static analysis (§4.2), segmented fuzzing (§4.3), and end-to-end validation (§4.4).

4.1

Segmentation Strategies

We first define Progression APIs, based on which Proton identifies segment boundaries in the application code. We then discuss how segmenting at these boundaries reduces the complexity of fuzzing. Progression APIs. We define a Progression API as an API call that, when reached with attacker-controlled input, forwards that input to a new execution surface, enabling a new independently-fuzzable segment to begin. Progression APIs generalize the notion of message passing beyond explicit IPC, as listed in Table 1 at lines 1-5, along with their availability across processes and execution contexts. They include IPC mechanisms (ipcRenderer.send, port.postMessage), external fetch operations (fetch(T)) whose responses introduce new attacker-controlled content, and navigation and embedding APIs (win.loadURL(T), iframe.src=T) that load attacker-controlled content into a new execution context. Additionally, code execution APIs (eval(T), executeJavaScript(T)) act as Progression APIs when reached in a sandboxed renderer without Node.js access, where the gained execution enables IPC escalation toward a privileged process. Proton identifies Progression APIs as segment boundaries, and equivalently, intermediate sinks from the fuzzing perspective. The goals of fuzzing each segment

Problem Definition. The goal of Proton is to identify concrete exploitable control-flow paths where attacker-controlled inputs flow from one or multiple sources to a terminal sink, and decompose each path into independently-fuzzable segments at intermediate sinks, or Progression APIs. For any candidate path π, Proton decomposes it into consecutive segments seg(π) = {S1 , S2 , . . . , Sk }, where each segment Si is a program fragment with: (i) an input from a new external source (custom URI, server response, or file) or the output of segment Si−1 , and (ii) an output that either reaches a Progression API to forward to Si+1 , or a terminal sink in Sk .

Complexity of Segmented Fuzzing. If a path π is decomposed into semantically-preserving segments {S1 , . . . , Sk }, then a segmented fuzzing campaign explores each segment independently. Under this assumption, the total exploration cost becomes the sum of the state spaces of each of its segments O(|Ii | · Ni ). Electron’s multi-process architecture with Progression APIs at process boundaries creates natural opportunities for each of the three segmentation patterns below. To illustrate these benefits, and without loss of generality, we focus on the simplest case: decomposing a path π into two segments, Sa and Sb . In the remainder of this subsection, we identify the principles under which such segmentation yields substantial reductions in explorable state space enabling efficient exploit validation, also summarized in Table 2. Dataflow-Independent Segments. The first pattern arises when two segments receive inputs from independent external sources. For example, in the Paperlib case, Source U (the custom URI) and Source S (the CSRF-fetched server response) are independent. The content of each is controlled separately by the attacker. A monolithic fuzzer must explore their full cross-product |Ia | × |Ib |; segmentation reduces this to O(|Ia | · Na ) + O(|Ib | · Nb ), collapsing the input space from multiplicative to additive size. Partially Dependent Segments. The second pattern occurs when Sb receives a mixture of inputs: some derived from Sa ’s output, and some from an independent source. Electron’s

Table 2: Instruction complexity and speedup comparison across segmentation strategies.

chain multiple intermediate vulnerabilities, such as CSRF, JavaScript code execution, before it finally reaches an OS command injection.

Strategy

#Instructions

Baseline

O((Na + Nb )|Ia ||Ib |)

DF Indep.

O(Na |Ia | + Nb |Ib |)

Partial Dep.

O(Na |Ia | + Nb |Ia′ ||Ib |)

Fully Dep.

O(Nb |Ia′ |)

Catalog of Progression APIs and Terminal Sinks. The agent is given the catalog shown in Table 1, which enumerates known Progression APIs, which include IPC mechanisms, external fetch operations, navigation APIs, and conditional code execution APIs, along with terminal sinks, across Electron’s processes and execution contexts. On the source side, the catalog includes the three payload source types (U, S, F) with their corresponding code patterns (e.g., app.on(’open-url’), fetch(T), fs.readFile(T)) that serve as taint entry points. This catalog determines which APIs the agent flags as boundaries or exploitation targets during path analysis.

Speedup (×)

Example

End-to-end

|Ia ||Ib | |Ia | + |Ib | |Ib | |Ia′ | |Ia | |Ia′ |

Multi-source IPC URL parsing

IPC exemplifies this: the channel field is determined by Sa (fixing routing), while the content field can be an arbitrary attacker-controlled value. Once valid channel bindings are known, the content space Ib can be fuzzed independently. Let Ia′ ⊆ Ia be the subset of Sa ’s inputs that produce valid bindings. The computation of speedup can be found in Table 2. Fully Dependent Segments. The final pattern arises when Sb ’s input is entirely determined by Sa ’s output, and Sa performs an invertible transformation, which is common in Electron apps where attacker-supplied data is first parsed via new URL, JSON.parse, or decodeURIComponent. Invertibility means that given any valid parsed output, a corresponding input can be reconstructed, enabling Proton to bypass Sa entirely and fuzz directly over valid parsed values. In the Paperlib example, Segment A parses the custom URI via new URL and JSON.parse. Proton skips fuzzing Segment A and instead uses an input reconstructor to generate well-formed URIs backward from valid parsed outputs.

4.2

Static Progression Analysis

Proton’s static progression analysis takes the Electron application source code as input and produces, for each discovered exploitable path π: its segmentation seg(π) = {S1 , . . . , Sk }, per-segment fuzzing harnesses, and LLM-generated seeds. To achieve this, Proton employs an LLM agent that performs a comprehensive taint-style analysis over the target repository, guided by a system prompt (Appendix D) that provides three inputs: (1) a threat model and vulnerability description, (2) a catalog of Progression APIs and terminal sinks, and (3) structured analysis tasks defining what the agent must discover and produce. Threat Model and Vulnerability Description. The agent is given a precise definition of MPV as a source-to-sink exploit chain originating from external sources such as custom URI and propagating through multi-process data flows, IPC channels, and transformation layers. The key is that MPV might

Structured Analysis Tasks. The agent is instructed to search the entire codebase, locate all potential sources and sinks, trace dataflows across process boundaries, and group them into segments along the segmentation boundaries. For each discovered path, the agent must produce: (1) an analysis.md summarizing identified sources, sinks, and segment boundaries such as IPC communications; (2) a dataflow-segments.json enumerating each segment, its code location, process type, and linkage to neighboring segments; (3) per-segment fuzzing harnesses; and (4) LLMgenerated seeds for each segment’s initial corpus. We will detail the harness and seed generation in §4.3.

4.3

Segmented Fuzzing

Given the segments, harnesses, and initial seeds produced by static progression analysis, segmented fuzzing takes each segment Si as input and produces a set of concrete inputs that either reach a terminal sink or an intermediate sink, that is, a Progression API, within that segment. Proton fuzzes segments sequentially using three components: a fuzzing loop that drives execution, harnesses that serve as segment entries, and oracles that define success conditions. Fuzzing Loop. Algorithm 1 presents the segmented fuzzing workflow. For each segment Si , Proton first checks whether it contains only invertible operations (lines 5–7); if so, the segment is skipped during fuzzing and reconstructed later using the input reconstructor. For non-invertible segments, Proton instruments the program with the segment-specific harness and oracle, incorporating inputs from all previous segments (line 8), then executes fuzzing with the provided seeds (line 9). The fuzz function returns inputsi containing the inputs that successfully trigger the target segment oracle. If no valid inputs are found (lines 10–12), Proton terminates chain exploration, as subsequent segments cannot be reached. Otherwise, if the previous segment Si−1 was invertible (lines 13–16), Proton reconstructs its input by inverting from the current segment’s inputs and appends it to the chain. Proton then appends the current segment and its inputs to the chain

(line 17). Finally, Proton returns the complete chain (line 19), which contains the inputs needed to trigger each segment in the detected exploit path. Corpus. Each segment’s initial corpus comes from (a) the upstream segment’s Progression API outputs. Every observed output contributes its concrete argument and a taint annotation describing the attacker-controlled substring, and (b) LLM-generated seeds from static analysis, producing one representative input per parse branch. The first segment’s corpus is synthesized from the attacker model. Halting. A segment’s fuzzing campaign halts when any of the following conditions are met: (i) a terminal sink is reached, triggering the oracle and saving a proof-of-concept; (ii) coverage of the segment’s recognized branches saturates and no new Progression API output is observed in k iterations; or (iii) a global time budget expires. A global halt condition additionally fires when a terminal sink is reached in any segment reachable from S1 via a composable sequence of Progression API outputs, which constitutes a complete end-to-end proof-of-concept. Harness Synthesis. For each segment Si , Proton synthesizes a lightweight, in-place testing harness that directly triggers src(Si ) with a fuzzer-supplied byte buffer. The harness is generated automatically from the segment specification produced during static analysis. It reconstructs only the minimal program state needed for the segment, replaying the source (such as an event handler, IPC entry point, or function call) without executing prior segments. Each harness is materialized as a small source-code patch that registers a function under a global namespace, enabling the fuzzing engine to invoke it directly. The synthesized harness maps input bytes into the structured data expected by that segment (e.g., a URI string, a parsed object, an IPC message payload) while hard-coding irrelevant contextual values. For segments in renderer processes, Proton modifies the window initialization so that Node.js APIs are available and the fuzzing runtime can be loaded. Applied patches leave the application’s normal behavior intact while providing precise, segment-level fuzzing entry points. Oracle Design. Proton detects whether fuzz inputs successfully reach segment sinks snk(Si ) using two oracle strategies. Syntax-based oracles monitor parse-time or evaluation-time syntax errors emitted by APIs that validate their inputs. Such errors are strong indications that the fuzzer-generated input reached the API, broke out of its original context, and was parsed as code, following prior works [13, 16]. Canary-based oracles embed a unique marker into fuzz inputs and check for its presence in API arguments or side effects, including network navigation targets, file paths, and IPC messages. Detection of the canary confirms that input propagation reached the intended sink. An example of such a canary is depicted on the bottom-right corner of Figure 2.

Algorithm 1 Scaffold of segmented fuzzing workflow 1: Input: Program P, Segments Si , Harnesses harness1:k ,

Oracles oracle1:k , Seeds seeds1:k , Input Reconstructors invert1:k 2: Output: Valid segment chains with inputs 3: chain ← [] 4: for i = 1 to k do 5: if Si is invertible then 6: continue 7: end if 8: P(i) ← instrument(P, harnessi , oraclei , inputs1:i−1 ) 9: inputsi ← fuzz(P(i) , seedsi ) 10: if inputsi = 0/ then 11: break 12: end if 13: if Si−1 is invertible then 14: inputsi−1 ← inverti−1 (inputsi ) 15: chain.append((Si−1 , inputsi−1 )) 16: end if 17: chain.append((Si , inputsi )) 18: end for 19: return chain

4.4

End-to-end Validation

Finally, given the validated segments and their respective inputs, Proton performs end-to-end validation through two steps: payload composition and end-to-end testing. Payload Composition. Proton first composes the final exploit payload through backward propagation from the last segment to the first. For each segment Si (traversing from k to 1), Proton maps the fuzzing harness inputs to the original program variables of Si , then embeds this reconstructed data into segment Si−1 ’s canary placeholders to propagate the payload backward. Note that all segments except the last contain canary values in their inputs, as only the final segment’s input can trigger the syntax-based oracles. For example, in Figure 2, harness_C’s inputs buf are mapped back to msg.data as the array ["import-from", "https://$canary"] based on line 2 of the utility process code. Then, for Segment B, Proton replaces the canary in its fuzzing input args with this reconstructed array value. This process continues backward: Segment B’s args value is embedded into Segment A’s URL parameter. End-to-end Testing. Proton then executes the composed payload against the complete application to verify the exploit path works end-to-end. When the exploit chain involves multiple sources, Proton instruments the application to intercept and supply secondary payloads directly. Specifically, Proton inserts condition blocks that check if a requested resource (domain or file path) is valid and matches the source specified in the primary payload. If so, it returns the secondary source’s

payload instead of performing the actual fetch or file read.

5

Implementation

Proton implements specialized fuzzing workflows using segmented fuzzing, targeting multiple input sources, multiple processes, and diverse harnesses, and introduces engine-level canary detection to automatically identify when attackercontrolled inputs reach security-sensitive APIs. Building upon jazzer.js [14], a JavaScript fuzzing framework based on libfuzzer [17], the implementation consists of 1,130 lines of code changes modifying the Electron engine, 948 lines extending jazzer.js with additional instrumentation, and 1,012 lines of agentic workflows. To facilitate future research, we have opensourced Proton at https://anonymous.4open.science/r/proton. Static Analysis. Proton implements agentic static analysis using Claude Opus 4.7 as the underlying LLM, while Claude Code serves as the agentic framework. The agent operates with a standard toolchain including file reading, file writing, directory traversal, and code search functionalities. Fuzzing. Proton instruments targets at two levels. At the framework level, it modifies Electron’s source and the Node.js standard library to hook APIs serving as segment oracles (sinks in Table 1) and external input APIs. At the application level, it injects harness code and JavaScript-specific coverage feedback. For main and utility processes, Proton hooks Node.js module loading for runtime instrumentation; for renderer processes, it instruments code at compile time via build plugins (e.g., vite.config.ts). Validation. Proton uses an LLM agent with the standard toolchain extended with a tool to launch applications with custom URI payloads for end-to-end payload validation.

6

Evaluation

We systematically evaluate Proton through the following five research questions (RQs): • RQ1 [Zero-days]: How many zero-day MPVs does Proton discover in real-world Electron applications, and what is the impact of these vulnerabilities? • RQ2 [Accuracy]: What are the false positive and false negative rates of Proton? • RQ3 [Performance]: How does Proton perform across its two phases? In Phase I, how many candidate paths and segments are produced per application, and how long and how many tokens does static analysis take? In Phase II, how long does fuzzing each segment take in terms of timeto-exposure (TTE)? • RQ4 [LLM Ablation]: What is the contribution of LLMgenerated harnesses and seeds to Proton’s detection capability? Specifically, how does Proton perform when LLM-

generated harnesses and seeds are replaced with templates or random ones? • RQ5 [Segmentation Ablation]: How does Proton’s segmented fuzzing compare to monolithic end-to-end fuzzing?

6.1

Experimental Setup

Dataset. We collected open-source Electron applications from GitHub by identifying repositories with electron listed as a dependency in package.json and over 100 stars, spanning projects from Jan. 2010 to April 2026. To focus on applications with external sources such as custom URI handling, we filtered for repositories containing "open-url" or "second-instance" in their codebase. This yielded 589 Electron applications. We will release the dataset upon acceptance. Environment. All experiments were conducted on a Mac workstation with an Apple M4 Pro processor and 24 GB of memory, running macOS 15.7.2. Proton uses claude-opus-4-7 for agentic static analysis.

6.2

RQ1: Zero-day Vulnerabilities

In this subsection, we answer the research question regarding the zero-day vulnerabilities detected by Proton. We define a detected vulnerability as a zero-day Message Progression Vulnerability vulnerability if there is no prior public disclosure and it is confirmed by a human expert with a successful end-to-end exploit. In total, Proton discovered 23 zero-day vulnerabilities: 22 leading to remote code execution and one enabling arbitrary file write. Table 3 presents a selective list of those zero-day vulnerabilities, including the affected applications’ details, payload sources, vulnerability consequences, and disclosure status. Many of the affected applications are highly popular, with up to 60k stars, demonstrating that MPV vulnerabilities affect widely-used software. The vulnerable applications span diverse categories including note-taking software, AI desktop assistants, email clients, music players, browsers, and document readers. This diversity indicates that MPV vulnerabilities are not limited to specific application types but represent a systemic risk across the Electron ecosystem. We responsibly disclosed all vulnerabilities through GitHub Security Advisories or direct email to maintainers. Of the 23 vulnerabilities, 11 have been assigned CVEs, and 13 have been acknowledged by maintainers, with 11 already fixed to date. We were also rewarded a bug bounty by Vercel for the discovery of the MPV vulnerability in Hyper. The discovered vulnerabilities exhibit diverse vulnerability code patterns across payload sources and sink contexts. Among them, four vulnerabilities require Remote Server Response, where the URI triggers the application to fetch and process content from attacker-controlled servers, such as

Table 3: [RQ1] A selective list of zero-day MPV S detected by Proton. The column “Payload Sources" indicates the attack vectors. The “Consequence" column shows exploitation impact. The “Status" column indicates disclosure status: Fixed (patch released), Acknowledged (maintainer confirmed but not yet fixed), or Reported (under review). Application

Category

AFFiNE Note Motrix Download Mgr. Hyper Terminal Cherry Studio AI Client Mailspring Email Client DevHub Dev Tool MusicFreeDesktop Music Player Pinokio AI App Launcher Deepchat AI Client LBRY Desktop Media Streaming Eidos AI Data Mgr. Thorium Reader E-book Reader Paperlib Reference Mgr. TidGi-Desktop Note Muffon Music Streaming Dive Docker Tool Vieb Web Browser nanovault Crypto Wallet

Stars

Version

Payload (U/F/S)

Safe Config.

59.7k 49.8k 44.5k 35.4k 16.8k 10.0k 7.0k 5.7k 4.9k 3.5k 3.0k 2.4k 2.0k 1.9k 1.9k 1.6k 1.5k 186

v0.25.1 v1.8.19 v4.0.0-canary.5 v1.4.11 v1.16.0 v4.0.3 v0.0.8 v3.9.0 v0.3.0 v0.53.9 v0.21.0 v3.2.2 v3.1.10 v0.12.4 v2.2.0 v0.9.3 v12.3.0 v1.2.1

U U U U U U U+S U+F U U+F U U+S U+S U U+S U U U

✓ ✓ ✓ ✓ ✓ ✓ ✓ ✗ ✓ ✗ ✓ ✓ ✗ ✓ ✓ ✓ ✗ ✓

Exploit Chain

Status

CVE/Advisory

LFI → RCE Fixed CVE-2026-XXXX AFW Reported – Acknowledged – RCE JSE → RCE Fixed CVE-2025-XXXX RCE Reported – JSE → RCE Reported – RCE Acknowledged CVE-2025-XXXX CSRF → LFI → RCE Fixed CVE-2025-XXXX DOM XSS → RCE Fixed CVE-2025-XXXX LFI → RCE Reported CVE-2025-XXXX JSE → SBE → RCE Fixed CVE-2025-XXXX CSRF → LFI → RCE Fixed GHSA-XXX-XXX CSRF → LFI → DOM XSS → RCE Fixed CVE-2025-XXXX JSE → RCE Fixed GHSA-XXX-XXX CSRF → DOM XSS → RCE Fixed CVE-2025-XXXX JSE → RCE Fixed CVE-2025-XXXX LFI → RCE Fixed GHSA-XXX-XXX JSE → RCE Reported CVE-2025-XXXX

Payload: U=(Custom) URI, F=File System, S=Remote Server; Safe Config.: ✓: the exploitation works under the default safe configuration (nodeIntegration=false, contextIsolation=true, and sandbox=true); ✗: otherwise; Exploit Chain: CSRF: Client-side Request Forgery; DOM XSS: DOM Cross-site Scripting; SBE: Sandbox Escape; JSE: JavaScript Code Execution; LFI: Local File Inclusion; RCE: OS-level Remote Code Execution.

downloading plugins (MusicFreeDesktop), retrieving metadata (Muffon), downloading ebooks (Thorium Reader), or fetching references (Paperlib). Two vulnerabilities require local file access, where the URI triggers applications to load a local file via dangerous APIs, such as requiring JavaScript files via require (Pinokio) or loading local HTML via window.loadURL (LBRY Desktop). Table 3 also indicates whether exploitation succeeds under the default safe configuration (nodeIntegration=false) in the Safe Config. column. Entries marked ✓exploit the application through message progression rather than relying on unsafe configurations, distinguishing our work from prior work focused on unsafe configuration-caused issues [7].

6.3

RQ2: Accuracy

Proton’s detection pipeline operates in two phases. Phase I (agentic static analysis) flagged 116 out of 589 applications as containing potentially exploitable paths. Phase II (segmented fuzzing) then fuzzes the segments in each flagged application, producing 26 apps with proofs-of-concept that reach a terminal sink. Of the remaining flagged applications, fuzzing either timed out within the four-hour budget or failed to reach a terminal sink. Of the 26 confirmed cases, 23 lead to either OS-level Remote Code Execution (RCE) or Arbitrary File Write (AFW). We evaluate the accuracy of Phase II reports below. False Positives. Proton considers a path exploitable when endto-end validation succeeds with a working proof-of-concept that triggers the sink canary, indicating that the input achieves

code execution in one of the main, utility, or renderer processes. Under Proton’s threat model, we only consider vulnerabilities that lead to RCE or AFW as true positives. Since renderer process code execution may require additional exploitation steps that cannot be easily validated through oracles, Proton conservatively reports all code execution instances for manual evaluation. Among the 26 apps that Proton fuzzes to reach a terminal sink, manual expert evaluation determined that three of them cannot be escalated to RCE or AFW, yielding a false positive rate of 11.5% (3/26). The three cases reach the terminal sink but can not compose into valid end-to-end exploits. Two reach openExternal as the terminal sinks, while the code filters the argument with http or https protocols. The other one reaches new Function as the terminal sink in a runtime context where require is not available. As a result, reaching the function still prevents it from executing arbitrary code. False Negatives. Evaluating false negatives requires a ground truth dataset of known MPV, but no such dataset exists, and no prior tools exist for MPV detection. To assess potential false negatives, we take three complementary approaches. First, we conducted an extensive search across the NVD database, GitHub security advisories, security disclosure platforms, and technical blogs, yielding only one publicly documented realworld MPV case [18] that is triggered by a fully external resource like a custom URI. The vulnerability exploits a redirection chain: the attacker causes the Electron application to load a website vulnerable to redirection, then the redirected attacker-controlled page calls require directly (because the renderer has nodeIntegration enabled). We ran Proton on

this case and confirmed it successfully detects the vulnerability, by reporting the vulnerable path, and reaches loadURL as a terminal sink during fuzzing. Second, we randomly sampled 30 applications from the 90 flagged by Phase I that Proton did not confirm as exploitable during Phase II fuzzing, and had two experts manually inspect their code for RCE or AFW vulnerabilities. None of the 30 were confirmed exploitable. Third, we randomly sampled 30 applications from the 473 applications not flagged by Phase I and manually inspected them for exploitable MPV. Together, these three assessments suggest that Proton achieves low false negative rates across both phases of its pipeline.

Table 4: [RQ3] Average time and token cost for static analysis and harness generation for vulnerable projects with 100k+ Lines of Code (LoC). All times are in minutes.

6.4

Segmented Fuzzing. Table 5 shows the number of fuzzing segments, process types, their sources and sinks, and the timeto-exposure (TTE) for each segment across vulnerable applications. TTE measures the elapsed time from the start of fuzzing until a generated input triggers an oracle, that is, either reaching an intermediate sink or a terminal sink. The median TTE across all vulnerabilities is 28 minutes, with 82% of vulnerabilities discovered within the 30 minutes of fuzzing. Single-segment vulnerabilities are resolved quickly. The shortest TTE of 13 seconds for Cherry Studio indicates cases where the vulnerability is directly reachable with minimal seed mutation. Multi-segment vulnerabilities take longer. Paperlib’s four-segment chain requires 2h38m total, with one segment (M2: rpc.postMessage) accounting for 2h20m due to complex parsing constraints. We will discuss comparing the TTE to baseline fuzzing later.

RQ3: Performance

We evaluate Proton’s performance across its two phases: agentic static analysis (Phase I) and segmented fuzzing (Phase II). Static Progression Analysis. Phase I flagged 116 out of 589 applications as potentially vulnerable, which produce 209 dataflows and 419 segments in total. Figure 3 shows the distribution of reported dataflows and segments per application across the full dataset. Among the 116 flagged applications, the majority (80.2%) have one or two candidate dataflows. Each of the flagged applications has, on average, 1.80 candidate dataflows and 3.61 segments. Table 4 presents detailed metrics for selected vulnerable applications with over 100k LoC, including the number of segments, analysis time, harness generation time, and token consumption. Note that harness generation applies only to Phase I flagged applications. Among the 116 flagged applications, the median analysis time is around six minutes with a median token consumption of 141k tokens. Across all 589 applications, the median analysis time is 2.42 minutes (this is because many do not contain vulnerable paths and the analysis stops early) with a median token consumption of 126k tokens. Even for the largest projects with over 100k LoC, the agentic static analysis is completed within sixteen minutes, showing its scalability.

#Apps (log)

1,000 100

1,000

473

36

32 15

10

10

5

24

18

12

11 4

3 3 3

2

1

1

0 1 2 3 4 5 6 #Dataflows

(a) Dataflows per application.

1

LoC

Taint Ana. Time

Harness Gen. Time

Tokens (k)

Hyper Cherry Studio Muffon Eidos Paperlib Median (I) Median (ALL)

162k 140k 129k 120k 119k 88k 65k

6.10 5.55 5.90 6.90 5.08 6.03 2.42

4.75 3.77 5.05 4.30 8.40 8.07 7.72

146 150 133 156 157 141 126

I: 116 Phase I report vulnerable apps; ALL: 589 total apps.

Scalability Analysis. Phase I and Phase II together take around 30 minutes on average, with a maximum of three hours for applications with large codebases and complex attack chains. This time cost, combined with full parallelizability across applications, makes Proton practical for large-scale MPV detection in Electron applications.

6.5

RQ4: Contribution of LLM Components

Proton uses LLMs for taint analysis and harness/seed generation. Since the static taint analysis is central to Proton’s design, we ablate only the latter two against non-LLM baselines (template harnesses, random seeds), with results in Table 6.

473

100

61

App

1

1

0 2 4 6 8 10 12 #Segments

(b) Segments per application.

Figure 3: [RQ3] Distribution of detected dataflows and segments per application (n = 589).

Harnesses. LLM-generated harnesses are critical for renderer process fuzzing, where applications implement heterogeneous IPC handlers that template-based harnesses cannot generalize across. Replacing them with templates reduces detection from 23/23 to 6/23 (random seeds) and 11/23 (LLM seeds), dropping 17 and 12 vulnerabilities, respectively, as many segments fail to initialize correctly and never reach their target sinks. Seeds. Beyond harnesses, good seeds are essential for branch exploration. LLM-generated seeds leverage semantic understanding of the application’s input format to produce struc-

Table 5: [RQ3] Per-segment and cumulative Time-toExposure (TTE) for multi-segment vulnerable paths under segmented fuzzing. Proton Application Seg

Inter./Terminal Sink

Seg TTE

Total TTE

Deepchat

M1 R1

sendToRenderer v-html

8s 1h12min9s

1h12min17s

Dive

M1 R1

webContents.send spawn

23s 9m32s

9m55s

Motrix

M1 R1

sendCommandToAll aria2.addUri

21s 13m49s

14m10s

muffon

M1 R1 M2

webContents.send() openNewTab v-html

37s 2m27s 55s

3m59s

paperlib

M1 R2 U1 R2

postMessage get rpc.postMessage innerHTML

33s 17m20s 2h20m11s 5s

2h38m9s

pinokio

M1 R1 M2

loadNewWindow res.redirect(w) require

14s 43s 12m43s

13m40s

TidGi Desktop

M1 R1 M2

executeJavaScript wikiOperationInServer new Function()

1m17s 27m1s 13m1s

41m19s

Thorium Reader

M1 M2 M3 R1

httpGet writeStream.pipe webContents.send webview.setAttribute

32s 2h49m15s 35m8s 21s

3h25m16s

turally valid initial inputs. With LLM harnesses fixed, replacing LLM seeds with random seeds reduces detection to 18/23; the five missed cases all involve complex parsing where random seeds fail to reach the first segment’s oracle. LLM seeds also accelerate discovery, reducing average TTE from 30m22s to 17m9s. Table 6: [RQ6] Contribution of LLM components in Proton. Harness

Seeds

Detected

Avg. TTE

Avg. Tokens

Template Template LLM

Random LLM Random

6/23 11/23 18/23

40m12s 28m04s 30m22s

— 47k 109k

LLM

LLM

23/23

17m9s

156k

6.6

RQ5: Segmented vs. End-to-End Fuzzing

Since no prior work exists for MPV detection, we implement an end-to-end fuzzing baseline based on jazzer.js, to serve as a baseline. To ensure fair comparison, we instrument the baseline with identical oracles and initial seeds as Proton. Both approaches have a four-hour time limit for fuzzing per application. Zero-day Detection. Among the 23 zero-day MPV S detected by Proton, the baseline only succeeded in 6, with the remaining 17 timing out. All baseline successes are single-segment

vulnerabilities where the terminal sink is directly reachable from the first input boundary. For other multi-segment vulnerabilities, the baseline fails to propagate inputs across process boundaries within the time budget. For example, it fails to reach the first postMessage sink in Paperlib within four hours, while Proton reaches the terminal sink in 2h38m via segmented fuzzing with an input reconstructor handling the invertible URI parsing. Edge Coverage. Table 7 compares edge coverage achieved by Proton and the baseline after four hours across 53 sampled applications. Proton achieves substantially higher coverage on vulnerable multi-segment applications. For example, 98.2% more edges on eidos. Specifically, the coverage improvement appears in multi-segment vulnerabilities, consistent with the complexity analysis in §4.1: segmentation allows Proton to explore deeper program states across processes, within the same time budget. Table 7: [RQ5] Edge coverage comparison of Proton against baseline, over a selective list of apps reported with candidate paths with multiple segments. Application

Baseline EdgeCov@4h

Proton EdgeCov@4h

Deepchat

1,646

1,750

+6.3%

eidos

685

1,358

+98.2%

Mailspring

345

772

+123.8%

muffon

389

433

+11.3%

MusicFreeDesktop

299

555

+85.6%

Motrix

327

672

+105.5%

paperlib

525

1,150

+119.0%

pinokio

633

799

+26.2%

Thorium Reader

1,148

1,576

+37.3%.

TidGi-Desktop

594

1,128

+89.9%

median(S)

477

892

+87.0%

S: 53 sampled apps, including 23 vulnerable ones and an additional 30 from phase I reports.

7

Discussion

Mitigation. Secure Electron configuration and other mitigations have been extensively studied [7,9–11]. On the handling side, defenses include: prompting users before handling external URIs, sanitizing inputs before dangerous APIs, validating domains via allowlists, isolating untrusted content in webviews, and configuring renderers with safe configurations enabled. On the triggering side, browsers and other applications that can invoke custom URIs should display the full URI string in confirmation dialogs, to enable users to identify malicious URIs. Generalizability of Segmented Fuzzing. Segmented fuzzing generalizes beyond Electron to any multi-process target. The

segmentation opportunities, including IPC boundaries, external input entry points, and invertible transformations, are broadly applicable. Porting requires adapting the agentic analysis to identify target-specific boundary APIs and implementing framework-specific instrumentation for harnesses, oracles, and reconstructors. Limitations. Proton’s agentic static analysis may miss complex dataflows when they span non-standard libraries, template engines, or LLM SDKs that require modeling beyond core Node.js and Electron APIs. LLM reasoning over such code may be incorrect due to limited training on recent libraries, inaccessible native addon source, and context window constraints. These inherent limitations we leave to future work.

8

Related Work

Security of Electron Applications. Prior work on Electron security has focused on two main attack vectors. First, several studies [6, 7] examined vulnerabilities arising from unsafe configurations. Second, other works [9–11] investigated malicious in-app user inputs and studied the defense of such vulnerabilities. In contrast, the exploitation of Message Progression Vulnerability, which needs to chain multiple vulnerabilities through cross-process messaging, has largely been ignored with no academic investigations. Web Application Fuzzing. Traditional web fuzzers employ grey-box coverage feedback [12, 19, 20], data flow tracking [21–23], predicate synthesis [24–26], and LLM-generated grammars [27–29] to explore deep program states. However, these fuzzers assume a single-process model [30–32] and cannot be easily adapted to Electron’s multi-process architecture. Segmented fuzzing via program slicing [33], function-level harnesses [34], or protocol modeling [35–37] shares our isolation goal, but cannot trace IPC flows across Electron processes or synthesize harnesses. Agentic Program Analysis. LLM-assisted static analysis systems such as IRIS [38], LLMDFA [39], MoCQ [40], and QLCoder [41] augment dataflow reasoning or synthesize vulnerability queries, but operate on single-process programs and static code graphs. Agentic frameworks, including GPT-4 Analyst [42, 43], LLM4Fuzz [44], FuzzGPT [45], and Locus [46], iteratively refine inputs or fuzzing predicates but assume monolithic execution contexts.

9

Conclusion

In this paper, we present Proton, the segmented fuzzing framework for detecting Message Progression Vulnerability in Electron applications. Proton decomposes complex cross-process exploit paths into independently fuzzable segments, enabling efficient fuzzing. We evaluated Proton against 589 real-world

Electron applications, discovering 23 zero-day vulnerabilities, including 22 exploitable that enable remote code execution, with 11 CVEs to date. Our findings demonstrate that the Message Progression Vulnerability is critical yet overlooked in Electron applications, and our open-source release of Proton helps developers identify these vulnerabilities.

References [1] A. Fass, D. F. Somé, M. Backes, and B. Stock, “DoubleX: Statically detecting vulnerable data flows in browser extensions at scale,” in Proceedings of the 2021 ACM SIGSAC Conference on Computer and Communications Security (CCS), 2021. [2] J. Yu, S. Li, J. Zhu, and Y. Cao, “Coco: Efficient browser extension vulnerability detection via coverage-guided, concurrent abstract interpretation,” in Proceedings of the 2023 ACM SIGSAC Conference on Computer and Communications Security, ser. CCS ’23. New York, NY, USA: Association for Computing Machinery, 2023, p. 2441–2455. [Online]. Available: https://doi.org/10.1145/3576915.3616584 [3] S. Son and V. Shmatikov, “The postman always rings twice: Attacking and defending postMessage in HTML5 websites,” in Proceedings of the 20th Annual Network and Distributed System Security Symposium (NDSS), 2013. [4] A. Barth, C. Jackson, and J. C. Mitchell, “Securing frame communication in browsers,” in 17th USENIX Security Symposium (USENIX Security 08). San Jose, CA: USENIX Association, Jul. 2008. [Online]. Available: https://www.usenix.org/conference/17th-u senix-security-symposium/securing-frame-communication-browsers [5] M. Steffens and B. Stock, “PMForce: Systematically analyzing postMessage handlers at scale,” in Proceedings of the 2020 ACM SIGSAC Conference on Computer and Communications Security (CCS), 2020. [6] D. LLC, “Electronegativity: A static analysis tool for electron applications,” 2022, accessed: 2026-07-22. [Online]. Available: https://github.com/doyensec/electronegativity [7] M. M. Ali, M. Ghasemisharif, C. Kanich, and J. Polakis, “Rise of inspectron: Automated black-box auditing of cross-platform electron apps,” in 33rd USENIX Security Symposium (USENIX Security 24), 2024, pp. 775–792. [8] B. Altpeter, “An analysis of the state of electron security in the wild,” Bachelor’s Thesis, Technische Universität Braunschweig, Braunschweig, Germany, 2020. [Online]. Available: https://benjamin-a ltpeter.de/doc/thesis-electron.pdf [9] Z. Yang, S. P. Chung, J. Chen, R. Zhang, B. Saltaformaggio, and W. Lee, “Coindef: A comprehensive code injection defense for the electron framework,” in 2025 IEEE Symposium on Security and Privacy (SP). IEEE, 2025, pp. 3127–3144. [10] Z. Jin, S. Chen, Y. Chen, H. Duan, J. Chen, and J. Wu, “A security study about electron applications and a programming methodology to tame dom functionalities.” in NDSS, 2023. [11] F. Xiao, Z. Yang, J. Allen, G. Yang, G. Williams, and W. Lee, “Understanding and mitigating remote code execution vulnerabilities in cross-platform ecosystem,” in Proceedings of the 2022 ACM SIGSAC Conference on Computer and Communications Security, 2022, pp. 2975–2988. [12] E. Trickel, F. Pagani, C. Zhu, L. Dresel, G. Vigna, C. Kruegel, R. Wang, T. Bao, Y. Shoshitaishvili, and A. Doupé, “Toss a fault to your witcher: Applying grey-box coverage-guided mutational fuzzing to detect sql and command injection vulnerabilities,” in 2023 IEEE Symposium on Security and Privacy (SP), 2023, pp. 2658–2675. [13] E. Güler, S. Schumilo, M. Schloegel, N. Bars, P. Görz, X. Xu, C. Kaygusuz, and T. Holz, “Atropos: Effective fuzzing of web applications for {Server-Side} vulnerabilities,” in 33rd USENIX Security Symposium (USENIX Security 24), 2024, pp. 4765–4782.

[16] E. Trickel, F. Pagani, C. Zhu, L. Dresel, G. Vigna, C. Kruegel, R. Wang, T. Bao, Y. Shoshitaishvili, and A. Doupé, “Toss a fault to your witcher: Applying grey-box coverage-guided mutational fuzzing to detect sql and command injection vulnerabilities,” in 2023 IEEE symposium on security and privacy (SP). IEEE, 2023, pp. 2658–2675. [17] LLVM Project, “libfuzzer: a library for coverage-guided fuzz testing,” https://llvm.org/docs/LibFuzzer.html, 2025, accessed: 2026-07-22. [18] Spaceraccoon, “Open sesame: Escalating open redirect to rce with electron code review,” https://spaceraccoon.dev/open-sesame-escal ating-open-redirect-to-rce-with-electron-code-review/, Aug. 2020, accessed: 2026-07-22. [19] S. Luo, A. Herrera, P. Quirk, M. Chase, D. C. Ranasinghe, and S. S. Kanhere, “Make out like a (multi-armed) bandit: Improving the odds of fuzzer seed scheduling with t-scheduler,” in Proceedings of the 19th ACM Asia Conference on Computer and Communications Security, ser. ASIA CCS ’24. New York, NY, USA: Association for Computing Machinery, 2024, p. 1463–1479. [20] T. Kim, S. Hong, and Y. Cho, “Aimfuzz: Automated function-level in-memory fuzzing on binaries,” in Proceedings of the 19th ACM Asia Conference on Computer and Communications Security, ser. ASIA CCS ’24. New York, NY, USA: Association for Computing Machinery, 2024, p. 1510–1522. [21] M. Wang, J. Liang, C. Zhou, Z. Wu, J. Fu, Z. Su, Q. Liao, B. Gu, B. Wu, and Y. Jiang, “Data coverage for guided fuzzing,” in 33rd USENIX Security Symposium (USENIX Security 24). Philadelphia, PA: USENIX Association, Aug. 2024, pp. 2511–2526. [22] J. Park, Y. Kim, and I. Yun, “ RGFuzz: Rule-Guided Fuzzer for WebAssembly Runtimes ,” in 2025 IEEE Symposium on Security and Privacy (SP). Los Alamitos, CA, USA: IEEE Computer Society, May 2025, pp. 920–938. [23] J. Kim, D. J. Tian, and B. E. Ujcich, “ Chimera: Fuzzing P4 Network Infrastructure for Multi-Plane Bug Detection and Vulnerability Discovery ,” in 2025 IEEE Symposium on Security and Privacy (SP). Los Alamitos, CA, USA: IEEE Computer Society, May 2025, pp. 3088– 3106. [24] J. Zhu, C. Shen, Z. Li, J. Yu, Y. Chen, and K. Pei, “Locus: Agentic predicate synthesis for directed fuzzing,” 2025. [25] C. Wang, W. Meng, C. Luo, and P. Li, “ Predator: Directed Web Application Fuzzing for Efficient Vulnerability Validation ,” in 2025 IEEE Symposium on Security and Privacy (SP). Los Alamitos, CA, USA: IEEE Computer Society, May 2025, pp. 886–902. [26] G. Lee, D. Xu, S. Salimi, B. Lee, and M. Payer, “Syzrisk: A changepattern-based continuous kernel regression fuzzer,” in Proceedings of the 19th ACM Asia Conference on Computer and Communications Security, ser. ASIA CCS ’24. New York, NY, USA: Association for Computing Machinery, 2024, p. 1480–1494. [27] R. Meng, M. Mirchev, M. Böhme, and A. Roychoudhury, “Large language model guided protocol fuzzing,” in Proceedings of the 31st Annual Network and Distributed System Security Symposium (NDSS), vol. 2024, 2024. [28] Y. Dong, X. Meng, N. Yu, Z. Li, and S. Guo, “ Fuzz-Testing Meets LLMBased Agents: An Automated and Efficient Framework for Jailbreaking Text-to-Image Generation Models ,” in 2025 IEEE Symposium on Security and Privacy (SP). Los Alamitos, CA, USA: IEEE Computer Society, May 2025, pp. 373–391.

[14] C. I. Testing, “Jazzer.js: Coverage-guided, in-process fuzzing for node.js,” 2023, accessed: 2026-07-22. [Online]. Available: https://github.com/CodeIntelligenceTesting/jazzer.js

[29] Y. Zhou, F. Yang, Z. Song, K. Zhang, J. Chen, and K. Zhang, “Liftfuzz: Validating binary lifters through context-aware fuzzing with gpt,” in Proceedings of the 2024 on ACM SIGSAC Conference on Computer and Communications Security, ser. CCS ’24. New York, NY, USA: Association for Computing Machinery, 2024, p. 3778–3792.

[15] Future-Scholars, “Paperlib: An open-source academic paper management tool,” 2025, gitHub repository, accessed 22 Jul 2026. [Online]. Available: https://github.com/Future-Scholars/paperlib

[30] J. Liu, Y. Shen, Y. Xu, and Y. Jiang, “Leveraging binary coverage for effective generation guidance in kernel fuzzing,” in Proceedings of the 2024 on ACM SIGSAC Conference on Computer and

Communications Security, ser. CCS ’24. New York, NY, USA: Association for Computing Machinery, 2024, p. 3763–3777. [31] J. Eom, S. Jeong, and T. Kwon, “Fuzzing javascript interpreters with coverage-guided reinforcement learning for llm-based mutation,” in Proceedings of the 33rd ACM SIGSOFT International Symposium on Software Testing and Analysis, ser. ISSTA 2024. New York, NY, USA: Association for Computing Machinery, 2024, p. 1656–1668. [32] J. Zhu, M. Lin, T. Yin, Z. Cai, Y. Wang, R. Chang, and W. Shen, “Crossfire: Fuzzing macos cross-xpu memory on apple silicon,” in Proceedings of the 2024 on ACM SIGSAC Conference on Computer and Communications Security, ser. CCS ’24. New York, NY, USA: Association for Computing Machinery, 2024, p. 3749–3762. [33] L. Chen, Q. Cai, Z. Ma, Y. Wang, H. Hu, M. Shen, Y. Liu, S. Guo, H. Duan, K. Jiang, and Z. Xue, “Sfuzz: Slice-based fuzzing for real-time operating systems,” ser. CCS ’22. New York, NY, USA: Association for Computing Machinery, 2022, p. 485–498. [34] A. Murali, N. Mathews, M. Alfadel, M. Nagappan, and M. Xu, “Fuzzslice: Pruning false positives in static analysis warnings through functionlevel fuzzing,” in Proceedings of the IEEE/ACM 46th International Conference on Software Engineering, ser. ICSE ’24. ACM, Feb. 2024, p. 1–13. [35] X. Feng, R. Sun, X. Zhu, M. Xue, S. Wen, D. Liu, S. Nepal, and Y. Xiang, “Snipuzz: Black-box fuzzing of iot firmware via message snippet inference,” 2021. [36] J. Ba, M. Böhme, Z. Mirzamomen, and A. Roychoudhury, “Stateful greybox fuzzing,” in 31st USENIX Security Symposium (USENIX Security 22). Boston, MA: USENIX Association, Aug. 2022, pp. 3255–3272. [37] J. Li, S. Li, G. Sun, T. Chen, and H. Yu, “Snpsfuzzer: A fast greybox fuzzer for stateful network protocols using snapshots,” IEEE Transactions on Information Forensics and Security, vol. 17, pp. 2673– 2687, 2022. [38] Z. Li, S. Dutta, and M. Naik, “Iris: Llm-assisted static analysis for detecting security vulnerabilities,” 2025. [39] C. Wang, W. Zhang, Z. Su, X. Xu, X. Xie, and X. Zhang, “Llmdfa: Analyzing dataflow in code with large language models,” 2024. [40] P. Li, S. Yao, J. S. Korich, C. Luo, J. Yu, Y. Cao, and J. Yang, “Automated static vulnerability detection via a holistic neuro-symbolic approach,” 2025. [41] C. Wang, Z. Li, S. Dutta, and M. Naik, “Qlcoder: A query synthesizer for static analysis of security vulnerabilities,” 2025. [42] L. Cheng, X. Li, and L. Bing, “Is gpt-4 a good data analyst?” 2023. [43] D. Noever, “Can large language models find and fix vulnerable software?” 2023. [44] C. Shou, J. Liu, D. Lu, and K. Sen, “Llm4fuzz: Guided fuzzing of smart contracts with large language models,” 2024. [45] Y. Deng, C. S. Xia, C. Yang, S. D. Zhang, S. Yang, and L. Zhang, “Large language models are edge-case fuzzers: Testing deep learning libraries via fuzzgpt,” 2023. [46] J. Zhu, C. Shen, Z. Li, J. Yu, Y. Chen, and K. Pei, “Locus: Agentic predicate synthesis for directed fuzzing,” 2025.

Appendix A

Open Science

We provide the following artifacts to support reproducibility and future research. All artifacts are available at https:// anonymous.4open.science/r/proton and will remain accessible after the submission deadline. Proton Engine. We release the full Proton implementation, including: (1) the patch for Electron framework modifications with engine-level instrumentation for canary detection, Progression API hooks, and IPC interception; (2) the extended jazzer.js fuzzing runtime with additional JavaScript-specific coverage feedback, segment harness registration, and oracle integration; and (3) the scripts that coordinate Phase I and Phase II across applications. LLM-based Agentic Workflow. We release the complete agentic static analysis and harness synthesis workflow, including: (1) the system prompts for the taint analysis and segmentation agent and the harness synthesis agent (Appendix D); (2) the LLM-generated analysis.md and dataflow-segments.json outputs for all vulnerable applications; (3) the synthesized harness patch files (<id>. harness.patch) for each segment; and (4) the LLMgenerated seeds for each segment’s initial corpus. Dataset. We release two datasets: (1) the complete list of all 589 Electron applications collected from GitHub, including their repository URLs, versions, and star counts at the time of collection; and (2) the curated list of 23 vulnerable applications, including their confirmed exploit chains, proofof-concept payloads, and CVE identifiers. For applications with pending disclosure, exploit details will be released following the 45-day remediation period. Vulnerability Disclosures. All 23 zero-day vulnerabilities have been responsibly disclosed to the respective maintainers. Proof-of-concept exploits for patched vulnerabilities are included in the artifact. For vulnerabilities still under remediation, proof-of-concept details will be added to the artifact repository upon public disclosure.

Appendix B

Ethical Considerations

We ensure that our study adheres to standard ethical guidelines for security research. All analyzed code was collected from publicly available open-source GitHub repositories in compliance with the platforms’ terms of service. No private or user-sensitive data was accessed. All application testing was conducted offline on local machines, with no impact on online servers or production systems. Regarding vulnerability disclosure, we responsibly reported all identified vulnerabilities to affected vendors and allowed a 45-day remediation period before public disclosure. As of this writing, we have received 13 acknowledgments and 11 fixes, and 11 CVE identifiers have been assigned.

… Electron Framework Bundled: Chromium + Node.js + libuv Renderer Renderer Processes Renderer Chromium Chromiumpages, pages,DOM DOM Chromium pages, DOM Node Integration Enabled

Preload Exposed APIs Spawns

Utility Utility Utility Process Process Processes

Delegates

Configures

Main Process App lifecycle, Native APIs

Native Modules Node native addons, OS integrations, Electron APIs

Figure 4: Electron architecture.

Appendix C

Exploitation Techniques

In this section, we explain the exploitation techniques used to escalate code execution in renderer processes to arbitrary command execution. Unsafe Window Configuration. Electron provides security configurations for renderer processes, including contextIsolation and nodeIntegration. Misconfigurations can enable code execution to escalate to command execution: • Direct Access via nodeIntegration. When node integration is enabled and context isolation is disabled, renderer processes have direct access to Node.js APIs. This is commonly seen in applications whose renderers need to use Node.js APIs. • Prototype Pollution. When context isolation is disabled but node integration remains disabled, the renderer and preload contexts share the same JavaScript environment, separated only by closure scope. Attackers can exploit this by overwriting built-in prototypes (e.g., Function.prototype.apply) to intercept function calls in the preload context and leak privileged objects. For example, in the Thorium Reader vulnerability, overwriting Function.prototype.apply allowed capturing the ipcRenderer object when preload scripts invoked apply. Once ipcRenderer is obtained, attackers can further hook EventEmitter.prototype.emit to leak the process object by triggering Node.js event system gadgets (e.g., by exceeding the max listener count to trigger warnings). With the leaked process object, attackers gain arbitrary command execution via process.binding("spawn_sync"). Preload Script APIs. Applications often expose custom APIs

Table 8: Categorization of IPC communication mechanisms across Electron’s multi-process architecture. For each IPC type, we show: the communicating parties with directionality, and code patterns for both sender and receiver. IPC Channels

Parties

Sender Code Patterns

Receiver Code Patterns

Pre-defined IPCs

Renderer → Main Renderer ↔ Main Main → Renderer

ipcRenderer.send(C, Msg) R = ipcRenderer.invoke(C, Msg) webContents.send(C, Msg)

ipcMain.on(C, F);ipcMain.addListener(C, F) ipcMain.handle(C, F) ipcRenderer.on(C, F);ipcRenderer.addListener(C, F)

Event Handlers

Renderer → Main Renderer → Main

window.open(URL) location.assign(URL)

webContents.setWindowOpenHandler(F) webContents.on("will-navigate", F)

Internal Protocols

Renderer ↔ Main

window.location.href = P

protocol.handle(P, F)

Pre-defined Message Ports

Main → Utility Utility → Main

child.postMessage(Msg) proc.parentPort.postMessage(Msg)

process.parentPort.on(’message’, F) child.on(’message’, F)

Custom Message Ports

Any ↔ Any∗

port.postMessage(Msg)

port.on(F); port.onmessage(F)

C=Channel name, Msg=Message data, F=Handler function, P=Protocol scheme, R=Return value. →: One-way communication; ↔: Bidirectional communication. ∗ : Includes Main-Utility (M-U), Main-Renderer (M-R), Utility-Renderer (U-R), Renderer-Renderer (R-R), and Utility-Utility (U-U) communications.

from preload scripts through contextBridge. If preload scripts expose the ipcRenderer object or wrappers, attackers can invoke arbitrary IPC handlers in the main process. Vulnerable handlers that execute commands without validation can lead to direct command execution. Similarly, exposed APIs using Node.js functionality (e.g., file operations, shell execution) without sanitization can be abused for privilege escalation. Main Process Event Handlers. Besides IPC handlers, Main processes can also register event handlers for renderer actions such as navigation and window creation. Navigation handlers like setWindowOpenHandler may call dangerous APIs such as shell.openExternal without validating destinations, enabling command execution through specially crafted URLs. V8 Vulnerability. When sandbox is disabled and the application uses an outdated Electron version, attackers can exploit known V8 vulnerabilities to achieve arbitrary code execution, bypassing Electron security configurations. Script Pivot. Finally, when direct escalation is not possible due to isolated contexts, attackers can pivot to more privileged renderer contexts. From a compromised iframe, attackers can use postMessage to achieve XSS in the parent context or force top-level navigation to load attacker-controlled content.

Appendix D

Agent Design

In this section, we detail the design of our static analysis agent as well as the harness synthesis agent.

D.1

Taint Analysis and Segmentation Agent

The taint analysis and segmentation agent performs two things simultaneously: one is to start from the open-url handler source to trace to an actual RCE sink, and the other is to produce dataflow segments. The high-level prompt (with details removed to save space) is shown in Listing 1. Note

that the categorization of IPC communication machanisms across Electron’s multi-process architecture (taxonomized in Table 8) is included in the prompt for the LLM agent to find precise segmentation boundaries. One sample output pair of segment source and sink is depicted in Listing 3. Empirically, typical agent trajectory starts from grepping the pattern of open-url to find the sources, and then iteratively trace through the dataflow to read more and more files. At some point, we observe agent using grepping tool to find sink patterns by writing regexes that generalize our specified taxonomy, which further leads the agent to find effective exploitable paths.

D.2

Harness Synthesis Agent

Given the segmented dataflow produced in §4.2, the next challenge is to instantiate each segment as a fuzzable entry point. For a given segment, fuzzing should begin directly at its sub-source so that fuzzing can focus on the semantics of the segment while avoiding redundant work and long execution chains. To achieve this, Proton uses an LLM-driven agent to synthesize in-place fuzzing harnesses, each packaged as a patch file automatically inserted into the Electron application source code. The process is guided by a second structured prompt that provides the agent with: • Segmentation result: analysis.md and dataflow-segments.json from the taint analysis, including all discovered sources, their process locations, and the sinks and subsequent sources they connect to. • Detailed task specification: defining what a harness must do: take a Uint8Array from the fuzzer, convert it into the structured input expected at that segment’s source, replay the segment’s entry point (e.g., invoking app.emit("open-url", ...), calling an IPC handler, or directly invoking a function), and expose the harness to the fuzzing engine via global.__proton__.harness. • Constraints and requirements: including where har-

1 2 3 4 5 6

You are a security analyst auditing Electron applications for unsafe open-url handling vulnerabilities. We have identified a class of vulnerability which we named Message Progression Vulnerability ( ,→ MPV). Assuming the Electron application is installed inside of a user’s system, when the user click on a...

7 8 9 10 11 12 13

16 17 18

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

39 40 41 42 43

At the end, please come up with two artifacts: 1. an ‘analysis.md‘ which contains the summary of your analysis of the code base. List out the discovered potential sources and sinks. Note that the goal is not to find just a single dataflow; but multiple dataflows with multiple potential sub-dataflow segments. 2. an ‘dataflow-segments.json‘ which is a json list that looks like the following ‘‘‘ json [ { "id": <a unique identifier>, "type": "source | sink", "process": "main | renderer | utility", "file_name": <the relative file name>, "line_num": <the line number>, "comment": <some comment about the node>,

46 47 48 49 50 51

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

76 77 78 79 80

8 9 11 12 13 15 16

Listing 1: LLM prompt for static analysis and segmentation.

Due to the complex nature of Electron applications, the dataflow may not be linear--that is, it could be considered as a multi-staged dataflow with multiple segments. For instance, there could be a dataflow that starts within Main process, and through an IPC call, go into the renderer process...

17 18 20 21 22 23 24 25

## Task Description Your task would be that for each detected source come up with a testing harness. A testing harness at its core, would be a function that takes in a buffer or an uint8array. It should contain the code necessary to convert the buffer into structured input to continue the execution of the current segment, ignoring all the prior segments...

26 27 28 29 30 31 32 33

However, to make the testing harness actually runnable, we need to properly expose the testing harness. The actual synthesized harness should have the form of a diff patch, which specifies in which file and in which line we would like to remove lines or add new lines. Please name the file ‘<source_id>.harness.patch‘ for each source stated in the dataflow-segments.json.

34 35 36 38 39 40 41 42 43 45 46 47 48 49 50 51 53 54 55 56 57 58 59 60 61

## Harness Example Here we give a concrete example of a harness that can be synthesized for our purpose: ‘‘‘ts export function urlFuzzInitialize() { (global as any).__proton__.harness = function (buf: Buffer | Uint8Array): void { const constructedUrl = harness(buf); try { app.emit(’open-url’, makeOpenUrlEvent(), constructedUrl); } catch (e) { // ... } } } ‘‘‘ ... ## Harness as Patches Generate patches that look like the following: ‘‘‘ --- a/main.ts +++ b/main.ts @@ -1,5 +1,6 @@ function initialize() { printf("Hello, world!\n"); + urlFuzzInitialize(); } ‘‘‘

62 63 64 65 66 67 68

This file should be directly applicable by running git patch. It is okay to have multiple files being modified. The criteria should be that, once the application is loaded (all the modules being ready), there should be our fuzzing harness registered in ‘global.__proton__‘.

69 70 71 72 73 74

# Analysis Task Your are now working on the ‘{app}‘ repository. - source code directory: ‘./repos/{app}/‘ - output directory: ‘./analysis-outputs/{app}/‘ As instructed, please perform thorough security analysis on the ‘{app}‘ repository.

# Harness Generation You are a security analyst auditing Electron applications for unsafe open-url handling vulns. We have identified a class of vulnerability or attack which we named Message Progression Vulnerability (MPV). Assuming ,→ the Electron application is installed inside of a user’s system, when the user click on a potentially compromised link in a browser, that URI may have a prefix of ‘my-app://‘ which is handled by the Electron app...

10

52

# Additional Information **1. Code Execution (XSS/RCE)** - ‘executeJavaScript()‘, ‘eval()‘, ‘new Function()‘ - ‘innerHTML‘, ‘outerHTML‘, ‘document.write()‘, ‘v-html‘. Example payload: ‘myapp://xss?code=<script>alert(1)</script>‘ ... # Notes - Please be comprehensive and search all javascript related files including .js, .ts (javascript or typescript) as well as the hybrid files related to front-end frameworks such as .vue or .jsx or .tsx for Vue and React applications... - External taint sources could come from remote requests (fetch(...)) or local file read (read(...)) especially if it happens to be that the arguments or urls to these functions are not fully controlled... - When you see that there is a window.loadURL or redirection with tainted URL or payload, you should find all the potentially connected process handlers to start subsequent segments.

74 75

6

44

// if we have a sink "sink_type": "require | html-inject | js-inject | ipc-call | xss | navigation | rce", "sink": <exact code pattern of the sink>, "connected_source": <the id of the source> }, ...] ‘‘‘

52 53

5

37

// if we have a source "source_type": "open-url-handler | uncontrolledfile-read | response-received | ...", "source": <exact code pattern of the source>, "connected_sink": <the id of the connected sink>, "introducing_new_taint": true | false,

44 45

4

19

37 38

3

14

Your job is to systematically analyze the repository to find potential source and sink, and finding whether they could be connected via multiple segments in different processes...

19 20

2

7

Due to the complex nature of Electron applications, the dataflow may not be linear--that is, it could be considered as a multi-staged dataflow with multiple segments. For instance, there could be a dataflow that starts within Main process, and through an IPC call, go into the renderer process...

14 15

1

75 76 77 78 79 80

# Harness Generation Task Your are now working on the ‘{app}‘ repository. - source code directory: ‘./repos/{app}/‘ - analysis directory: ‘./analysis-outputs/{app}/‘ - output directory ‘./harness-outputs/{app}/‘ Everytime you encounter a new source you should create ‘<source-id>.harness.patch‘. The patch should be comprehensive such that an automated script can launch the app and start a fuzzing campaign using ‘jazzer.js‘. As instructed, please perform thorough security analysis on the ‘{app}‘ repository.

Listing 2: LLM prompt for synthesizing fuzzing harness.

nesses may be inserted, how to preserve functional behavior, how to handle renderer-process sources (by enabling nodeIntegration), and how to structure each harness patch so that it is directly applicable via git apply. The full prompt is shown in Listing 2. Harness Generation Workflow. For every source node in the segmentation output, Proton instructs the agent to generate a dedicated patch file named <source-id>.harness.patch. The patch contains all code edits needed to:

1

[{

2

"id": "src-1-main-openurl-handler-150", "type": "source", "process": "main", "file_name": "app/main/main-entry.ts", "line_num": 150, "comment": "Primary open-url event handler that...", "source_type": "open-url-handler", "source": "app.on(\"open-url\", (event, urlStr) ...", "connected_sink": "sink-1-window-mgmt-loadurl-106", "introducing_new_taint": true }, { "id": "sink-1-window-mgmt-loadurl-106", "type": "sink", "process": "main", "file_name": ".../window-proc-mgnt-service.ts", "line_num": 106, "comment": "BrowserWindow.loadURL() called with...", "sink_type": "navigation", "sink": "windows.get(id).loadURL(entryURL)", "connected_source": "src-1-main-openurl-handler-150", "subsequent_source": [] }, ...]

3

• inject a new initializer (e.g., urlFuzzInitialize() or a source-specific variant) early in the application startup path; • define the harness function that maps bytes to the source’s expected input shape. The agent reuses surrounding program logic whenever possible, and may hard-code unrelated values to preserve determinism; • bind the harness into the global namespace under global.__proton__.harness, allowing an external driver (Jazzer.js) to locate and execute it; • ensure the correct runtime environment, which may include editing BrowserWindow creation to enable Node.js APIs or injecting Jazzer.js bootstrap code into renderer entry files. Example Output. Harness patches generated by Proton resemble conventional source patches (Listing 4). These patches are self-contained: applying them to the repository yields an instrumented application that, when launched, automatically registers all synthesized harnesses. The fuzzing engine can then start a campaign by calling global.__proton__.harness(buf), which replays the sub-source with a fuzzed payload.

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

Listing 3: Sample JSON output from agentic static analysis. 1 2 3 4 5 6

--- a/ main . ts +++ b/ main . ts @@ -42 ,6 +42 ,7 @@ function bootstrap () { initializeWindow () ; + urlFuzzInitialize () ; }

Listing 4: An example harness patch that injects the fuzzer initialization function in the bootstrap method of the application.

Record · ID 394326 · SHA-256 a3f554997ae49659
Retrieved via Conceptio — every document is proof-bundled with source, license, and retrieval metadata.