Seguridad
Para información sobre cómo revelar las vulnerabilidad de Electrón dirigirse a SECURITY.md.
Para las vulnerabilidades de Chromium: Electron se mantiene al día con versiones alternativas de Chromium. Para más información, consulte el documento de Calendario de Lanzamiento de Electron.
Prólogo
Como desarrolladores web, solemos disfrutar de la sólida red de seguridad del navegador — los riesgos asociados con el código que escribimos son relativamente pequeños. A nuestras páginas web se les concede poderes limitados en un sandbox, y confiamos en que nuestros usuarios disfrutan un buscador construido por un gran equipo de ingenieros que es capaz de responder rápidamente a recientes amenazas de seguridad descubiertas.
Cuando se trabaje con Electron, es importante entender que Electron no es un navegador web. Te permite construir aplicaciones de escritorio llenas de utilidades con tecnologías web familiares, pero tu código tiene mucho más poder. JavaScript puede acceder a los archivos del sistema, actividades del usuario y más. Esto permite que construyas aplicaciones nativas de alta calidad, pero los riesgos inherentes de seguridad escalan con el poder adicional concedido a tu código.
Con eso en mente, ten en cuenta que mostrar contenido arbitrario proveniente de fuentes poco confiables viene con un riesgo severo que Electron no está diseñado para manejar. De hecho, las aplicaciones Electron más populares (Atom, Slack, Visual Studio Code, etc) muestran principalmente contenido local (o confiable, contenido remoto seguro sin integración de Node) — si tu aplicación ejecuta código desde una fuente en línea, es tu responsabilidad el asegurarte de que el código no es malicioso.
Pautas generales
La seguridad es responsabilidad de todos
Es importante recordar que la seguridad de tu aplicación de Electron es el resultado de la seguridad general de los cimientos del framework (Chromium, Node.js), de Electron en sí mismo, todas las dependencias de NPM y tu propio código. Por tanto, es tu responsabilidad seguir algunas importantes mejores prácticas:
-
Mantenga su aplicación actualizada con la última versión liberada de Electron. Cuando libere su producto, también está compartiendo un conjunto compuesto de Electron, librerías compartidas de Chromium y Node.js. Vulnerabilidades afectando a estos componentes pueden impactar en la seguridad de su aplicación. Al actualizar Electron a la última versión, te aseguras de que las vulnerabilidades críticas (como los bypasses de nodeIntegration) ya estén corregidas y no puedan ser explotadas en tu aplicación. Para más informacón, vea "Use a current version of Electron".
-
**Evalue sus dependencias.**Mientras NPM provee más de medio millón de paquetes reusables, es su responsabilidad la elección de librerías confiables de terceros. Si utiliza librerías desactualizadas afectadas por vulnerabilidades conocidas o basado en código escasamente mantenido, la seguridad de su aplicación puede estar en peligro.
-
Adopte prácticas de programación segura. La primera línea de defensa de su aplicación es su propio código. Vulnerabilidades usuales, tales como Cross-Site Scripting (XSS), tienen un alto impacto en la seguridad en las aplicaciones Electron así es altamente recomendable adoptar políticas confiables de buenas prácticas en el desarrollo de software y realizar pruebas de seguridad.
Aislamiento para contenido no confiable
Un problema de seguridad existe siempre que recibes código de un lugar no confiable (e.g. un servidor remoto) y lo ejecutas localmente. Si un atacante de algún modo se las arregla para cambiar dicho contenido (bien sea atacando la fuente directamente, o interviniendo entre su aplicación y el destino real), será capaz de ejecutar códigos nativos en la máquina del usuario.
Bajo ninguna circunstancia deberías cargar y ejecutar código remoto con la integración de Node.js activada. En su lugar, use solo archivos locales (empaquetados junto con su aplicación) para ejecutar código Node.js. Para mostrar contenido remoto, use la etiqueta <webview> o un WebContentsView y asegúrese de desactivar el nodeIntegration y activar contextIsolation.
Las advertencias y recomendaciones de seguridad se imprimen en la consola de desarrollador. Solo se muestran cuando el nombre del binario es Electron, lo que indica que un programador está mirando actualmente a la consola.
Usted puede activar o desactivar estas advertencias forzosamente configurando ELECTRON_ENABLE_SECURITY_WARNINGS o ELECTRON_DISABLE_SECURITY_WARNINGS ya sea en process.env o en el objeto window.
Lista de comprobación: Recomendaciones de seguridad
Al menos debes seguir los siguientes pasos para mejorar la seguridad de su aplicación:
- Solo carga contenido seguro
- No habilitar la intergración de Node.js para contenido remoto
- Activar el aislamiento de contexto en todos los renderizadores
- Activar el aislamiento del proceso
- Usar
ses.setPermissionRequestHandler()en todas las sesiones que cargan contenido remoto - No desactives
webSecurity - Define un
Content-Security-Policyy usa reglas estrictas (i.e.script-src 'self') - No active
allowRunningInsecureContent - No active ajustes experimentales
- No use
enableBlinkFeatures <webview>: No useallowpopups<webview>: Verificar opciones y parámetros- Deshabilitar o limitar navegación
- Deshabilitar o limitar la generación de nuevas ventanas
- No utilice
shell.openExternalcon contenido no confiable - Usar una versión actual de Electron
- Validar el
senderde todos los mensajes IPC - Evite el uso del protocolo
file://y prefiera el uso de protocolos personalizados - Compruebe qué fusibles puede cambiar
- No exponer las API de Electron para contenido web no confiable
1. Solo carga contenido seguro
Cualquier recurso no incluido con tu aplicación debería ser cargado usando un protocolo de seguridad como HTTPS. En otras palabras, no uses protocolos inseguros como HTTP. De manera similar, recomendamos el uso de WSS antes de WS, FTPS antes de FTP, y así.
¿Por què?
HTTPS tiene dos beneficios principales:
- Asegura la integridad de los datos, afirmando que los datos no fueron modificados durante la transmisión entre tu aplicación y el host.
- Encripta el tráfico entre tu usuario y el host destino, haciendo más difícil escuchar a escondidas la información enviada entre tu aplicación y el host.
¿Còmo?
// Bad
browserWindow.loadURL('http://example.com')
// Good
browserWindow.loadURL('https://example.com')
<!-- Bad -->
<script crossorigin src="http://example.com/react.js"></script>
<link rel="stylesheet" href="http://example.com/style.css">
<!-- Good -->
<script crossorigin src="https://example.com/react.js"></script>
<link rel="stylesheet" href="https://example.com/style.css">
2. No habilitar la intergración de Node.js para contenido remoto
Esta recomendación es el comportamiento por defecto desde Electron 5.0.0.
Es primordial que no active la integración Node.js en ningún renderizador (BrowserWindow, WebContentsView, o <webview>) que carga contenido remoto. La meta es limitar los poderes que concedes al contenido remoto, aunque lo hace dramáticamente más difícil para un atacante lastimar a tus usuarios, ellos deberían ganar la habilidad de ejecutar JavaScript en tu página web.
Luego de esto, puedes conceder permisos adicionales para anfitriones específicos. Por ejemplo, si estás abriendo un BrowserWindows apuntado a https://example.com/, puedes dar a ese sitio web exactamente las capacidades que necesita, pero no más.
¿Por què?
Un ataque cross-site-scripting (XSS) es más peligroso si un atacante puede altar fuera del proceso de renderizado y ejecutar el código en la computadora del usuario. Ataques cross-site-scripting son muy comunes - y durante un problema, su poder es usualmente limitado a molestar a la página en dónde los están ejecutando. Desactivar la integración Node.js ayuda a prevenir un XSS de ser escalado en un llamado ataque de "Ejecución de Código Remoto".
¿Còmo?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
nodeIntegrationInWorker: true
}
})
mainWindow.loadURL('https://example.com')
// Good
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})
mainWindow.loadURL('https://example.com')
<!-- Incorrecto -->
<webview nodeIntegration src="page.html"></webview>
<!-- Correcto -->
<webview src="page.html"></webview>
Cuando desactivas la integración Node.js, todavía puedes exponer APIs a tu página web que consume módulos Node.js o características. Los scripts de precarga continúan teniendo acceso a require y otras características de Node.js, permitiendo a los desarrolladores exponer una API personalizada al contenido remotamente cargado a través de contextBridge API.
3. Habilitar el aislamiento de contexto
Aislamiento de contexto es el comportamiento por defecto en Electron desde 12.0.0.
Context isolation es un ajuste de Electron que permite a los desarrolladores ejecutar códigos en guiones de pre carga y en APIs de Electron en un contexto dedicado de JavaScript. En práctica, eso significa que los objetos globales como Array.prototype.push o JSON.parse no puede ser modificado por guiones por guiones ejecutándose en el proceso de renderizado.
Electron usa la misma tecnología que los Content Scripts de Chromium para activar este comportamiento.
Incluso cuando nodeIntegration: false es usado, para verdaderamente implementar un fuerte aislamiento y evitar el uso de primitivas de Node tambien se debe usar contextIsolation.
Tenga en cuenta que al inhabilitar el aislamiento de contexto para un proceso de renderizado mediante la configuración de nodeIntegration: true, también se inhabilita el proceso arenero para ese proceso. Consulte la sección a continuación.
Para más información sobre que es contextIsolation y como habilitarlo, consulte nuestra documentación dedicada en Context Isolation.
4. Activar el aislamiento del proceso
Esta recomendación es el comportamiento por defecto desde Electron 20.0.0.
Además, se puede implementar el arenero de procesos para todos los procesos de renderizado en toda la aplicación: Habilitar arenero globalmente
Inhabilita el aislamiento de contexto (consulte arriba) _también inhabilita el proceso arenero _, independientemente de lo predeterminado, sandbox: false o globalmente habilitado para el arenero!
Sandboxing es una característica de Chromium que usa el sistema operativo para limitar significativamente a lo que que el proceso de renderizado tiene acceso. Deberías activar el sandbox en todos los procesos de renderizado. No se recomienda la carga, lectura o el procesado de cualquier contenido que no sea de confianza en un proceso no protegido, incluido el proceso principal.
Para mas información acerca del Process Sandboxing y como habilitarlo por favor vea el siguiente documento Process Sandboxing.
5. Administrar solicitudes de permiso de sesión desde contenido remoto
Puede que hayas visto solicitudes de permiso mientras usas Chrome: aparecen cada vez que el sitio web intenta usar una característica que el usuario tiene que aprobar manualmente (como las notificaciones).
La API está basada en los Chromium permissions API e implementa el mismo tipo de permisos.
¿Por què?
Por defecto, Electron aprobará automáticamente todos los pedidos de permiso a menos que el desarrollador haya configurado manualmente un comerciante personalizado. Aunque es un sólido ajuste automático, los desarrolladores conscientes de la seguridad pueden querer asumir lo contrario.
¿Còmo?
const { session } = require('electron')
const { URL } = require('node:url')
session
.fromPartition('some-partition')
.setPermissionRequestHandler((webContents, permission, callback) => {
const parsedUrl = new URL(webContents.getURL())
if (permission === 'notifications') {
// Apruebe los permisos solicitados
callback(true)
}
// Verificar URL
if (parsedUrl.protocol !== 'https:' || parsedUrl.host !== 'ejemplo.com') {
// Deniega los permisos solicitados
return callback(false)
}
})
6. No desactives webSecurity
Esta recomendación es la predeterminada de Electron.
Usted ya pudo haber adivinado que al desactivar la propiedad webSecurity en un procesador de renderizado (BrowserWindow, WebContentsView, o <webview>) deshabilita funciones de seguridad elementales.
No deshabilite webSecurity en aplicaciones de producción.
¿Por què?
Desactivar webSecurity deshabilitará la política de mismo-origen y establecer la propiedad allowRunningInsecureContent a true. En otras palabras, permite la ejecución de código inseguro desde diferentes dominios.
¿Còmo?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
webSecurity: false
}
})
// Good
const mainWindow = new BrowserWindow()
<!-- Bad -->
<webview disablewebsecurity src="page.html"></webview>
<!-- Good -->
<webview src="page.html"></webview>
7. Define un contenido de política de seguridad
Un Contenido de Política de Seguridad (CSP) es una capa adicional de protección contra los ataques cross-site-scripting attacks y ataques de inyecciones de data. Recomendamos que ellos estén activados por cualquier página web cargada dentro de Electron.
¿Por què?
CSP permite que el servidor dando contenido pueda restringir y controlar los recursos que Electron puede cargar para esa página web dada. https://example.com debería estar permitido para guiones de pre carga de los orígenes que definiste mientras que los guiones de https://evil.attacker.com no debería tener permitido ejecutarse. Definir un CSP es una manera fácil de mejorar la seguridad de tus aplicaciones.
¿Còmo?
El siguiente CSP permitirá que Electron ejecute guiones desde la página web actual y desde apis.example.com.
// Bad
Content-Security-Policy: '*'
// Good
Content-Security-Policy: script-src 'self' https://apis.example.com
Cabeceras CSP HTTP
Electron respeta la cabecera HTTP de Content-Security-Policy la cual puede ser fijada utilizando el manipulador webRequest.onHeadersReceived de Electron:
const { session } = require('electron')
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': ['default-src \'none\'']
}
})
})
Etiqueta meta CSP
El mecanismo de entrega preferido de CSP es en una cabecera HTTP. Sin embargo, no es posible usar este método al cargar un recurso usando el protocolo file://. Esto puede ser útil en algunos casos para establecer una política directamente en una página en el marcador usando la etiqueta <meta>:
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
8. No active allowRunningInsecureContent
Esta recomendación es la predeterminada de Electron.
Por defecto, Electron no permitirá sitios webs cargados sobre HTTPS para cargar y ejecutar scripts, CSS, o plugins desde orígenes inseguros (HTTP). Establecer la propiedad allowRunningInsecureContent a true deshabilita esa protección.
Descargar la inicial HTML de un sitio web mediante HTTPS e intentar descargar recursos subsecuentes mediante HTTP es también conocido como "contenido mixto".
¿Por què?
Cargando contenido sobre HTTPS se asegura la autenticidad y la integridad de los recursos cargados mientras se cifra el trafico en si mismo. Ver la sección en only displaying secure content para más detalles.
¿Còmo?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
allowRunningInsecureContent: true
}
})
// Good
const mainWindow = new BrowserWindow({})
9. No active ajustes experimentales
Esta recomendación es la predeterminada de Electron.
Usuarios avanzados de Electron pueden habilitar las características experimentales de Chromium usando la propiedad experimentalFeatures.
¿Por què?
Las características experimentales son, como el nombre lo indica experimentales y no han sido activadas para todos los usuarios de Chromium. Además, es probable que no se haya probado su impacto en Electron como un conjunto.
Casos de uso legítimo existen, pero excepto que usted sepa lo que está haciendo, usted no debería habilitar esta propiedad.
¿Còmo?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
experimentalFeatures: true
}
})
// Good
const mainWindow = new BrowserWindow({})
10. No use enableBlinkFeatures
Esta recomendación es la predeterminada de Electron.
Blink es el nombre del motor de renderizado detrás de Chromium. Como con la propiedad experimentalFeatures, la propiedad enableBlinkFeatures permite a los desarrolladores habilitar características que han sido deshabilitada por defecto.
¿Por què?
En general, probablemente hay buenas razones si una función no fue habilitada por defecto. Casos de uso legítimo para habilitar funciones especificas existen. Como un desarrollador, usted debería saber exactamente por qué usted necesita habilitar una función, cuales son las ramificaciones, y como impacta las seguridad de su aplicación. Usted no debería habilitar funciones de forma especulativa bajo ninguna circunstancia.
¿Còmo?
// Bad
const mainWindow = new BrowserWindow({
webPreferences: {
enableBlinkFeatures: 'ExecCommandInJavaScript'
}
})
// Good
const mainWindow = new BrowserWindow()
11. No usar allowpopups para WebViews
Esta recomendación es la predeterminada de Electron.
Si usted está usando <webview>, tal vez necesite las páginas y guiones cargados en su etiqueta <webview> para abrir nuevas ventanas. El atributo allowpopups los habilita para crear BrowserWindows nuevo utilizado el método window.open(). tags <webview> de otra manera no se permite crear nuevas ventanas.
¿Por què?
Si usted no necesita ventanas emergentes, le conviene no permitir la creación de nuevos BrowserWindows por defecto. Esto sigue el principio de acceso de mínimamente requerido: No permita que un sitio web cree nuevas ventanas excepto usted sepa que se necesita esa función.
¿Còmo?
<!-- Bad -->
<webview allowpopups src="page.html"></webview>
<!-- Good -->
<webview src="page.html"></webview>
12. Verificar las opciones de WebView antes de la creación
Un WebView creado en un proceso de renderizado que no contenga integración habilitada de Node.js no será capaz de habilitar integración por sí mismo. Sin embargo, a WebView siempre creará un proco de renderizado independiente con su propio webPreferences.
Es una buena idea controlar la creación de nuevas etiquetas <webview> desde el proceso principal y verificar que su webPreferences no desactiven características de seguridad.
¿Por què?
Puesto que <webview> vive en el DOM, ellos pueden ser creados por un script corriendo en tu sitio web incluso si la integración con Node.js está descativada.
Electron habilita a desarrolladores a inhabilitar varias funciones de seguridad que controlan un proceso de renderizado. En la mayoría de los casos, desarrolladores no necesitas deshabilitar ninguno de esas funciones - y usted debería por lo tanto no permitir configuraciones diferentes para etiquetas <webview> creadas recientemente.
¿Còmo?
Antes que una etiqueta <webview> sea adjuntada, Electron va a disparar el evento will-attach-webview en el webContents hosting. Use el evento para evitar la creación de webViews con posibles opciones inseguras.
app.on('web-contents-created', (event, contents) => {
contents.on('will-attach-webview', (event, webPreferences, params) => {
// Eliminar los scripts de precargados si no se usan o verificar que su ubicación sea legítima
delete webPreferences.preload
// Deshabilitar la integración Node.js
webPreferences.nodeIntegration = false
// Verificar la URL que está siendo cargado
if (!params.src.startsWith('https://example.com/')) {
event.preventDefault()
}
})
})
Una vez más, esta lista simplemente minimiza el riesgo, pero no la elimina. Si su objetivo es mostrar un sitio web, un navegador será la opción mas segura.
13. Deshabilitar o limitar navegación
Si tu aplicación no tiene la necesidad de navegar o sólo necesita navegar a páginas conocidas, es una buena idea limitar la navegación directamente a ese alcance conocido, inhabilitando cualquier otro tipo de navegación.
¿Por què?
La navegación es un vector de ataque común. Si un atacante puede convencer a su aplicación para que navegue lejos de su página actual, posiblemente puede forzar a tu aplicación a abrir sitios web en Internet. Incluso si tu webContents están configurados para ser más seguros (como tener nodeIntegration deshabilitado o contextIsolation habilitado), conseguir que tu aplicación abra un sitio web aleatorio hará que el trabajo de explotar tu aplicación sea mucho mas fácil.
Un patrón común de ataque es que el atacante convence a los usuarios de tu aplicación a interactuar con la aplicación de tal manera que navegue a una de las páginas del atacante. Esto usualmente se hace vía links, plugins u otro contenido generado por el usuario.
¿Còmo?
Si su aplicación no tiene necesidad de navegación, puede llamar event.preventDefault() en un gestor will-navigate. Si sabes a que páginas tu aplicación puede navegar, revisa la URL en el manejador de evento y solo deja que ocurra la navegación si coincide con las URL que estás esperando.
Recomendamos que uses el parser para URLs de Node. Comparaciones simples de cadenas puede a veces engañar - una prueba startsWith('https://example.com') podría dejar pasar https://example.com.attacker.com.
const { app } = require('electron')
const { URL } = require('node:url')
app.on('web-contents-created', (event, contents) => {
contents.on('will-navigate', (event, navigationUrl) => {
const parsedUrl = new URL(navigationUrl)
if (parsedUrl.origin !== 'https://example.com') {
event.preventDefault()
}
})
})
14. Deshabilitar o limitar la generación de nuevas ventanas
Si tienes un conjunto de ventanas conocido, es una buena idea limitar la creación de ventanas adicionales en tu aplicación.
¿Por què?
Al igual que la navegación, la creación de nuevo webContents en un vector de ataque común. Los atacantes intentar convencer a tu aplicación a crear nuevas ventanas, frames u otros procesos renderer con más privilegios de lo que antes tenían; o con páginas abiertas que antes no pudieron abrir.
Si no tienes la necesidad de crear ventanas adicionales de la que sabes que tendrás que crear, desactivando la creación te compra un poco de seguridad extra sin costo alguno. Este comúnmente el caso de las aplicaciones que abre un BrowserWindow y no necesita abrir un número arbitrario de ventanas adicionales en tiempo de ejecución.
¿Còmo?
webContents delegará a su manipulador abierto de ventana antes de crear ventanas nuevas. El manejador recibirá, entre otros parámetros, la url que se solicito a la ventana para abrir y las opciones usadas para crearla. Recomendamos que registres un manejador para controlar la creación de ventanas y denegar la creacón de cualquier ventana inesperada.
const { app, shell } = require('electron')
app.on('web-contents-created', (event, contents) => {
contents.setWindowOpenHandler(({ url }) => {
// En este ejemplo, solicita al sistema operativo
// abrir esta url de estos eventos en el explorador por defecto.
//
// See the following item for considerations regarding what
// URLs should be allowed through to shell.openExternal.
if (isSafeForExternalOpen(url)) {
setImmediate(() => {
shell.openExternal(url)
})
}
return { action: 'deny' }
})
})
15. No utilice shell.openExternal con contenido no confiable
El módulo de intérprete cuyo openExternal API concede abrir un URI de protocolo dado con las utilidades del escritorio nativas. En macOS, por ejemplo, esta función es similar a la utilidad de línea de comandos open y abrirá la aplicación especifica basada en la URI y el tipo de archivo asociado.
¿Por què?
Empleo impropio de openExternal puede estar apalancado a compromiso del host del usuario. Cuando openExternal se usa con contenido no confiable, puede ser apalancado para ejecutar comandos arbitrarios.
¿Còmo?
// Incorrecto
const { shell } = require('electron')
shell.openExternal(USER_CONTROLLED_DATA_HERE)
// Correcto
const { shell } = require('electron')
shell.openExternal('https://example.com/index.html')
16. Usar una versión actual de Electron
Deberías esforzarte por usar siempre la última versión disponible de Electron. Cada vez que se lance una nueva versión principal, deberías intentar actualizar tu App de lo más rápido posible.
¿Por què?
Una aplicación construida con una versión anterior de Electron, Chromium y Node.js es un objetivo más fácil que una aplicación que está usando versiones más recientes de esos componentes. Generalmente hablando, los problemas de seguridad y exploits para viejas verciones de Chromium y Node.js están más ampliamente disponibles.
Ambos Chomium y Node.js impresionantes son impresionantes hazañas de ingeniería construidas por miles de talentosos desarrolladores. Dada su popularidad, su seguridad es cuidadosamente probada y analizada por investigadores de seguridad igualmente calificados. Muchos de esos investigadores revelan vulnerabilidades de manera responsable, lo que generalmente quiere decir que los investigadores darán a Chromium y Node.js algo de tiempo para solucionar los problemas antes de publicarlos. Tu aplicación será más segura si está ejecutando una versión reciente de Electron (y por tanto, Chromium y Node.js) para los cuales problemas de seguridad potenciales no son tan conocidos.
¿Còmo?
Migra tu aplicación una versión principal a la vez, mientras consultas el documento Breaking Changes de Electron para ver si hay código que necesita ser actualizado.
17. Validar el sender de todos los mensajes IPC
Siempre debe validar los mensajes IPC entrantes sender propiedad para asegurarse de que no está realizando acciones o enviando información a usuarios no confiables.
¿Por què?
Todos Frames Web pueden normalmente enviar mensajes IPC al proceso primario, incluyendo iframes y ventanas minores en unos escenarios. Si tienes un mensaje IPC que vuelve los datos del usuario al enviador via event.reply o performa acciones que van fovorecer el usuario, debes asegurarte que no estas escuchando a cadres web de terceras partes.
No hay que validar los mensajes IPC desender``sender predefinidos.
¿Còmo?
// Incorrecto
ipcMain.handle('get-secrets', () => {
return getSecrets();
});
// Correcto
ipcMain.handle('get-secrets', (e) => {
if (!validateSender(e.senderFrame)) return null;
return getSecrets();
});
function validateSender(frame) {
// Evalúe el host de la URL usando un analizador de URL real y una lista de permitidos
if ((new URL(frame.url)).host === 'electronjs.org') return true;
return false;
}
18. Evite el uso del protocolo file:// y prefiera el uso de protocolos personalizados
Servirían las páginas locales desde un protocolo personalizado en lugar del protocolo file://.
¿Por què?
El protocolo file:// obtiene más privilegios en Electron que en un navegador web e incluso en navegadores se trata de forma diferente a las URL http/https. Usar un protocolo personalizado te permite para estar más alineado con el comportamiento clásico de la URL web mientras conservas aún más control sobre lo que se puede cargar y cuándo.
Las páginas que se ejecutan en file:// tienen acceso unilateral a cada archivo de su máquina, lo que significa que los problemas de XSS pueden ser usados para cargar archivos arbitrarios de la máquina del usuario. El uso de un protocolo personalizado evita problemas como este, ya que permite limitar el protocolo para que solo sirva un conjunto específico de archivos.
¿Còmo?
Siga los ejemplos de protocol.handle para aprender a servir archivos/contenido desde un protocolo personalizado.
19. Compruebe qué fusibles puede cambiar
Electron viene con una serie de opciones que pueden ser útiles, pero una gran parte de las aplicaciones probablemente no las necesitan. Para evitar tener que construir tu propia versión de Electron, estos se pueden desactivar o usar Fuses.
¿Por què?
Algunos fuses, como runAsNode y nodeCliInspect, permitir que la aplicación se comporte de manera diferente cuando se ejecuta desde la línea de comandos usando variables de entorno específicas o argumentos CLI. Estos se pueden utilizar para ejecutar comandos en el dispositivo a través de la aplicación.
Esto puede permitir que scripts externos ejecuten comandos que potencialmente no estarían permitidos, pero para los que su aplicación podría tener los derechos necesarios.
¿Còmo?
@electron/fuses es un módulo que hicimos para hacer que sea fácil cambiar estos fusibles. Revisa el README de ese módulo para más detalles sobre el uso y posibles casos de error y consulte ¿Cómo vuelvo a los fusibles? en nuestra documentación.
20. No exponer las API de Electron para contenido web no confiable
No debes exponer directamente las APIs de Electron, especialmente IPC, a contenido web no confiable en tus scripts de precarga.
¿Por què?
Exponer API sin procesar como ipcRenderer.on es peligroso porque otorga a los procesos de renderizado acceso directo a todo el sistema de eventos de IPC, lo que les permite escuchar cualquier evento de IPC, no solo los destinados a ellos.
Para evitar esa exposición, tampoco podemos pasar devoluciones de llamada directamente a través de: El primer argumento a los callbacks de eventos IPC es un objeto IpcRendererEvent, que incluye propiedades como sender que proporcionan acceso a la instancia ipcRenderer subyacente. Incluso si solo escuchas eventos específicos, pasar el callback directamente significa que el renderizador obtiene acceso a este objeto de evento.
En resumen, queremos que el contenido web no confiable sólo tenga acceso a la información necesaria y a las API.
¿Còmo?
// Malo
contextBridge.exposeInMainWorld('electronAPI', {
on: ipcRenderer.on
})
// También malo
contextBridge.exposeInMainWorld('electronAPI', {
onUpdateCounter: (callback) => ipcRenderer. n('update-counter', callback)
})
// Buen
contextBridge. xposeInMainWorld('electronAPI', {
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', (_event, value) => callback(value))
})
Para obtener más información sobre qué es contextIsolation y cómo usarlo para proteger su aplicación, consulte el documento Aislamiento de contexto.