Sécurité
Pour en savoir plus sur la façon de déclarer correctement une vulnérabilité d'Electron, voir SECURITY.md.
Pour les vulnérabilités existantes en amont et propres à Chromium : Electron est tenu à jour par rapport aux nouvelles versions de Chromium. Pour plus d'informations, voir le document Electron Release Timelines.
Préface
Généralement, en tant que développeurs Web, nous apprécions le solide filet de sécurité que représente un navigateur - les risques associés au code que nous écrivons sont relativement faibles. Nos sites Web bénéficient de pouvoirs limités dans un bac à sable, et nous sommes convaincus que nos utilisateurs bénéficient d'un navigateur construit par une grande équipe d'ingénieurs capables de répondre rapidement aux menaces de sécurité récemment découvertes.
Lorsque vous travaillez avec Electron, il est important de comprendre qu’Electron n’est pas un navigateur web. Il vous permet de developper des applications de bureau riche en fonctionnalités avec des technologies web familières, mais votre code détient beaucoup plus de pouvoir. JavaScript peut ainsi accéder au système de fichiers, au shell et bien plus. Cela vous permet de développer des applications natives de haute qualité, mais les risques en matière de sécurité augmentent également en raison des pouvoirs supplémentaires accordés à votre code.
Dans cette perspective, sachez qu’afficher du contenu arbitraire de sources peu fiables présente énormément de risques pour la sécurité qu'Electron n’est pas censé gérer. En fait, les applications Electron les plus populaires (Atom, Slack, Visual Studio Code, etc) affichent principalement du contenu local (ou du contenu fiable distant et sans intégration de Node ) si votre application exécute du code à partir d'une source en ligne, il vous incombe de vous assurer que celui-ci n'est pas malveillant.
Directives générales
La sécurité est la responsabilité de tous
Il est important de se rappeler que la sécurité de votre application Electron dépend globalement de la sécurité du framework (Chromium, Node.js), d'Electron lui-même, de toutes les dépendances NPM et de votre code. Donc il est de votre responsabilité de suivre quelques bonnes pratiques importantes :
-
**Gardez votre application à jour avec la dernière version du framework Electron. ** Ceci est important, car lorsque vous publiez votre produit vous expédiez également un paquet composé d'Electron, de la bibliothèque partagée Chromium et de Node.js. Les vulnérabilités affectant ces composants peuvent affecter la sécurité de votre application. En mettant à jour Electron vers sa dernière version vous vous assurez que les vulnérabilités critiques (telles que nodeIntegration bypasses) sont déjà corrigées et ne pourront pas être exploitées dans votre application. Pour plus d'informations, voir "Utiliser une version actuelle d'Electron".
-
Évaluez vos dépendances. NPM fournit un demi-million de paquets réutilisables, mais il est de votre responsabilité de choisir des bibliothèques tierces fiables. Si vous utilisez des bibliothèques obsolètes affectées par des vulnérabilités connues ou si vous êtes dépendants d'un code mal maintenu, la sécurité de votre application pourrait être compromise.
-
Adoptez des pratiques de codage sécurisées. La première ligne de défense de votre application est votre propre code. Des vulnérabilités web courantes, telles que le cross-site scripting (XSS), ont un impact sur la sécurité plus élevé sur les applications Electron, c'est pourquoi il est fortement recommandé d'adopter des bonnes pratiques de développement de logiciel sécurisé et d'effectuer des tests de sécurité.
Isolation de contenu non fiable
Un problème de sécurité existe chaque fois que vous recevez du code d'une source non fiable (par exemple, un serveur distant) et que vous l'exécutez localement. À titre d'exemple, considérez un site Web distant affiché à l'intérieur d'une BrowserWindow
configurée par défaut. Si un attaquant parvient d'une manière ou d'une autre à modifier ledit contenu (soit en s'attaquant directement à la source, ou en se plaçant entre votre application et la destination voulue), il sera en mesure d'exécuter du code natif sur la machine de l'utilisateur.
Vous ne devez en aucun cas charger et exécuter du code distant avec l'intégration de Node.js activée. Utilisez plutôt des fichiers locaux (empaquetés avec votre application) pour exécuter du code de Node.js. Pour afficher du contenu distant, utilisez le tag <webview>
ou WebContentsView
et assurez-vous de désactiver nodeIntegration
et d'activer contextIsolation
.
Les avertissements de sécurité et les recommandations sont affichés dans la console du développeur. Ils n'apparaissent que lorsque le nom du binaire est Electron, indiquant ainsi qu'un développeur peut actuellement voir la console.
Vous pouvez forcer l'activation ou la désactivation de ces avertissements en définissant ELECTRON_ENABLE_SECURITY_WARNINGS
ou ELECTRON_DISABLE_SECURITY_WARNINGS
sur process.env
ou sur l’objet window
.
Checklist : recommandations de sécurité
Pour améliorer la sécurité de votre application, vous devriez au moins suivre ces conseils:
- Charger uniquement du contenu sécurisé
- Désactiver l'intégration de Node.js dans tous les moteurs de rendu qui affichent du contenu distant
- Activer l’isolation de contexte dans tous les moteurs de rendu
- Activer le sandboxing de processus
- Utiliser
session.setPermissionRequestHandler()
dans toutes les sessions chargeant du contenu distant - Ne pas désactiver
webSecurity
- Définissez une
Content-Security-Policy
et utilisez des règles restrictives (c.-à-d.script-src 'self'
) - Ne pas activer
allowRunningInsecureContent
- Ne pas activer les fonctionnalités expérimentales
- Ne pas utiliser
enableBlinkFeatures
<webview>
: N'utilisez pasallowpopups
<webview>
: Vérifier les options et les paramètres- Désactiver ou limiter la navigation
- Désactiver ou limiter la création de nouvelles fenêtres
- Ne pas utiliser
shell.openExternal
avec un contenu non fiable - Utiliser une version actuelle d'Electron
- Valider les
sender
de tous les messages IPC - Évitez l'utilisation du protocole
file://
et préférez l'utilisation de protocoles personnalisés - Vérifiez quels fuse vous pouvez modifier
Pour automatiser la détection de mauvaises configurations et de procédures non sécurisés, il est possible d'utiliser Electronegativity. For additional details on potential weaknesses and implementation bugs when developing applications using Electron, please refer to this guide for developers and auditors.
1. Charger uniquement du contenu sécurisé
Toutes les ressources non incluses dans votre application doivent être chargées à l’aide d’un protocole sécurisé tel que HTTPS
. En d’autres termes, n’utilisez pas de protocoles non sécurisés tels que HTTP
. De même, nous vous recommandons d’utiliser WSS
plutôt que WS
, FTPS
plutôt que FTP
et ainsi de suite.
Pourquoi ?
HTTPS
a trois principaux avantages :
- Il assure l'intégrité des données, certifiant que les données n'ont subi aucune modification durant le transfert entre votre application et l'hôte.
- Il encrypte le trafic entre votre l'utilisateur et l'hôte de destination, ce qui complique la tâche de quiconque voudrait épier les informations échangées entre l'hôte et votre application.
Comment ?
// Incorrect
browserWindow.loadURL('http://example.com')
// Correct
browserWindow.loadURL('https://example.com')
<!-- Incorrect -->
<script crossorigin src="http://example.com/react.js"></script>
<link rel="stylesheet" href="http://example.com/style.css">
<!-- Correct -->
<script crossorigin src="https://example.com/react.js"></script>
<link rel="stylesheet" href="https://example.com/style.css">
2. Ne pas activer l'intégration de Node pour du contenu distant
Cette recommandation correspond au comportement par défaut d'Electron depuis la version 5.0.0.
It is paramount that you do not enable Node.js integration in any renderer (BrowserWindow
, WebContentsView
, or <webview>
) that loads remote content. Le but est de limiter les permissions accordées aux contenus distants, ce qui complique drastiquement la tâche pour un attaquant qui souhaiterait nuire à vos utilisateurs (si jamais cet attaquant réussissait à exécuter du javascript sur votre site).
Après cela, vous pouvez accorder des permissions supplémentaires pour des hôtes spécifiques. Par exemple, si vous ouvrez une BrowserWindow pointant sur https://example.com/
, vous pouvez donner à ce site strictement les capacités dont il a besoin, mais pas plus.
Pourquoi ?
Une attaque de cross-site-scripting (XSS) est plus dangereuse lorsque l'attaquant peut sortir du processus de rendu et exécuter du code sur l'ordinateur de l'utilisateur. Les attaques de script inter-sites sont assez courantes - et bien qu’il s’agisse d’un problème, leur puissance est généralement limitée à perturber le site Web sur lequel elles sont exécutées. La désactivation de l’intégration node.js permet d’éviter qu’un XSS ne devienne une attaque dite « d’exécution de code à distance » (RCE).
Comment ?
// Incorrect
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
nodeIntegrationInWorker: true
}
})
mainWindow.loadURL('https://example.com')
// Correct
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})
mainWindow.loadURL('https://example.com')
<!-- Incorrect -->
<webview nodeIntegration src="page.html"></webview>
<!-- Correct -->
<webview src="page.html"></webview>
Lors de la désactivation de l'intégration de Node.js, vous pouvez toujours exposer à votre site web des API qui consomment des modules ou des fonctionnalités de Node.js. Les scripts de préchargement continuent d'avoir accès à require
et aux autres fonctionnalités de Node.js, permettant aux développeurs d'exposer une API personnalisée au contenu distant chargé via l'API de contextBridge .
3. Activer l’isolation du contexte
Cette recommandation correspond au comportement par défaut d'Electron depuis la version 12.0.0.
L'isolement de contexte est une fonctionnalité d'Electron permettant aux développeurs d'exécuter du code de scripts de préchargement et des API Electron dans un contexte JavaScript dédié. Dans la pratique cela signifie que les objets globaux comme Array.prototype.push
ou JSON.parse
ne peuvent pas être modifiés par les scripts exécutés dans le processus de rendu.
Electron utilise la même technologie que Chromium Content Scripts pour permettre ce comportement.
Même lorsque nodeIntegration: false
est utilisé, contextIsolation
doit également être utilisé pour vraiment appliquer une isolation forte et empêcher l'utilisation des primitives de Node.
Pour plus d'informations sur ce qu'est contextIsolation
et comment l'activer, veuillez voir notre document dédié Isolation du contexte.
4. Activer le sandboxing de processus
Le Sandboxing (mise en bac à sable) est une fonctionnalité de Chromium qui utilise le système d’exploitation pour limiter considérablement les processus de rendu auxquels ils ont accès. Vous devez activer le bac à sable dans tous les moteurs de rendu. Charger, lire ou traiter tout contenu non fiable dans un processus non protégé par le bac à sable, y compris le processus principal, n'est pas conseillé.
Pour plus d'informations au sujet du Sandboxing
et comment l'activer, veuillez voir notre document dédié Mise en bac à sable de processus.
5. Gérer les demandes d’autorisation de session à partir d'un contenu distant
Vous avez peut-être vu des demandes d'autorisation lors de l'utilisation de Chrome : elles apparaissent chaque fois que le site Web tente d'utiliser une fonctionnalité que l'utilisateur doit approuver manuellement ( comme les notifications).
L'API se base sur l'API de permissions Chromium et implémente le même type de permissions.
Pourquoi ?
Par défaut, Electron approuvera automatiquement toutes les demandes de permission, sauf si le développeur a manuellement configuré un gestionnaire personnalisé. Bien que la valeur par défaut soit solide, les développeurs soucieux de la sécurité pourraient vouloir assumer le contraire.
Comment ?
const { session } = require('electron')
const { URL } = require('url')
session
.fromPartition('some-partition')
.setPermissionRequestHandler((webContents, permission, callback) => {
const parsedUrl = new URL(webContents.getURL())
if (permission === 'notifications') {
// Approuve la demande de permissions request
callback(true)
}
// Vérification de l'URL
if (parsedUrl.protocol !== 'https:' || parsedUrl.host !== 'example.com') {
// Refuse la demande de permission
return callback(false)
}
})
6. Ne pas désactiver webSecurity
Cette recommandation est la valeur par défaut d’Electron.
You may have already guessed that disabling the webSecurity
property on a renderer process (BrowserWindow
, WebContentsView
, or <webview>
) disables crucial security features.
Ne désactivez pas webSecurity
dans les applications en production.
Pourquoi ?
Désactiver webSecurity
désactivera la politique de même origine et définira la propriété allowRunningInsecureContent
à true
. En d'autres termes, cela permet l'exécution de code non sécurisé à partir de différents domaines.
Comment ?
// Incorrect
const mainWindow = new BrowserWindow({
webPreferences: {
webSecurity: false
}
})
// Correct
const mainWindow = new BrowserWindow()
<!-- Incorrect -->
<webview disablewebsecurity src="page.html"></webview>
<!-- Correct -->
<webview src="page.html"></webview>
7. Définir une politique de sécurité de contenu
Une politique de sécurité de contenu (CSP) est une couche supplémentaire de protection contre les attaques de cross-site-scripting et d'injection de données. Nous recommandons qu'elle soit activée pour tout site Web que vous chargez dans Electron.
Pourquoi ?
CSP permet au serveur servant le contenu de restreindre et de contrôler les ressources pouvant être chargées par Electron pour cette page web. https://example.com
devrait être autorisé à charger des scripts depuis les origines que vous avez définies alors que les scripts de https://evil.attacker.com
ne devraient pas être autorisés à s'exécuter. Définir une CSP est un moyen facile d'améliorer la sécurité de votre application.
Comment ?
La CSP suivante permettra à Electron d'exécuter des scripts depuis le site web actuel et depuis apis.example.com
.
// Incorrect
Content-Security-Policy: '*'
// Correct
Content-Security-Policy: script-src 'self' https://apis.example.com
En-têtes HTTP pour la CSP
Electron respecte l'en-tête HTTP Content-Security-Policy
qui peut être défini en utilisant le gestionnaire webRequest.onHeadersReceived
d'Electron :
const { session } = require('electron')
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': ['default-src \'none\'']
}
})
})
Balise meta CSP
Le mécanisme de livraison préféré d'une CSP est un en-tête HTTP. Toutefois, il n’est pas possible d’utiliser cette méthode lors du chargement d’une ressource à l’aide du protocole file://
. Il peut être utile dans certains cas de définir une stratégie sur une page directement dans le balisage à l’aide d’une balise <meta>
:
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
8. Ne pas activer allowRunningInsecureContent
Cette recommandation est la valeur par défaut d’Electron.
Par défaut, Electron n'autorisera pas les sites Web chargés sur HTTPS
à charger et exécuter des scripts, CSS ou plugins à partir de sources non sécurisées (HTTP
). Définir la propriété allowRunningInsecureContent
à true
désactive cette protection.
Le chargement du HTML initial d'un site en HTTPS
et la tentative de chargement de ressources ultérieures via HTTP
est aussi connu sous le nom de "contenu mixte".
Pourquoi ?
Le chargement du contenu avec HTTPS
assure l'authenticité et l'intégrité des ressources chargées tout en chiffrant le trafic lui-même. Consultez la section sur l' affichage du contenu sécurisé uniquement pour plus de détails.
Comment ?
// Incorrect
const mainWindow = new BrowserWindow({
webPreferences: {
allowRunningInsecureContent: true
}
})
// Correct
const mainWindow = new BrowserWindow({})
9. Ne pas activer les fonctionnalités expérimentales
Cette recommandation correspond au comportement par défaut d’Electron.
Les utilisateurs avancés d’Electron peuvent activer les fonctionnalités expérimentales de Chrome en utilisant la propriété experimentalFeatures
et .
Pourquoi ?
Les fonctionnalités expérimentales sont, comme leur nom l’indique, expérimentales et n’ont pas été activées pour tous les utilisateurs de Chromium. De plus, leur impact sur Electron dans son ensemble n’a probablement pas été testé.
Il est parfois légitime de les implémenter, mais à moins que vous ne sachiez vraiment ce que vous faites, vous ne devriez pas autoriser ces fonctionnalités.
Comment ?
// Incorrect
const mainWindow = new BrowserWindow({
webPreferences: {
experimentalFeatures: true
}
})
// Correct
const mainWindow = new BrowserWindow({})
10. Ne pas utiliser enableBlinkFeatures
Cette recommandation est la valeur par défaut d’Electron.
Blink est le nom du moteur de rendu derrière Chromium. Comme pour experimentalFeatures
, la propriété enableBlinkFeatures
permet aux développeurs d'activer les fonctionnalités qui ont été désactivées par défaut.
Pourquoi ?
De manière générale, il y a probablement de bonnes raisons pour qu'une fonctionnalité ne soit pas activée par défaut. Il existe des cas d'utilisation légitime pour l'activation de fonctionnalités spécifiques. En tant que développeur , vous devriez savoir exactement pourquoi vous avez besoin d'activer une fonctionnalité, quelles en sont les conséquences et comment elle impacte la sécurité de votre application. En aucun cas vous ne devez vous permettre d'activer des fonctionnalités de manière spéculative.
Comment ?
// Mauvais
const mainWindow = new BrowserWindow({
webPreferences: {
enableBlinkFeatures: 'ExecCommandInJavaScript'
}
})
// Correct
const mainWindow = new BrowserWindow()
11. Ne pas utiliser allowpopups
pour les WebViews
Cette recommandation correspond au comportement par défaut d’Electron.
If you are using <webview>
, you might need the pages and scripts loaded in your <webview>
tag to open new windows. L'attribut allowpopups
leur permet de créer une nouvelle BrowserWindows
en utilisant la méthode window.open()
. Les balises <webview>
ne sont pas autorisées à créer de nouvelles fenêtres .
Pourquoi ?
Si vous n'avez pas besoin de popups, il vaut mieux ne pas autoriser la création de nouvelles BrowserWindows
par défaut. Cela suit le principe d'accès minimum requis : ne laissez pas un site web créer de nouvelles fenêtres popups à moins que vous ne sachiez qu'il a besoin de cette fonctionnalité.
Comment ?
<!-- Incorrect -->
<webview allowpopups src="page.html"></webview>
<!-- Correct -->
<webview src="page.html"></webview>
12. Vérifiez les options des WebViews avant leur création
Une WebView créé dans un processus de rendu sans l'intégration Node.js d'activé ne sera pas en mesure d'activer l'intégration elle-même. Cependant, une WebView créera toujours un processus de rendu indépendant avec ses propres webPreferences
.
It is a good idea to control the creation of new <webview>
tags from the main process and to verify that their webPreferences do not disable security features.
Pourquoi ?
Étant donné que les <webview>
résident dans le DOM, elles peuvent être créées par un script s’exécutant sur votre site Web , même si l'intégration de Node.js est désactivée.
Electron permet aux développeurs de désactiver diverses fonctionnalités de sécurité qui contrôlent un processus de rendu. In most cases, developers do not need to disable any of those features - and you should therefore not allow different configurations for newly created <webview>
tags.
Comment ?
Before a <webview>
tag is attached, Electron will fire the will-attach-webview
event on the hosting webContents
. Utilisez l'événement pour empêcher la création de webViews
avec des options potentiellement non sécurisées.
app.on('web-contents-created', (event, contents) => {
contents.on('will-attach-webview', (event, webPreferences, params) => {
// Retirer les scripts de preload si non utilisés ou vérifier que leur emplacement est légitime
delete webPreferences.preload
// Désactiver l'intégration de Node.js
webPreferences.nodeIntegration = false
// Verifer les URL à charger
if (!params.src.startsWith('https://example.com/')) {
event.preventDefault()
}
})
})
Encore une fois, cette liste ne fait que minimiser les risques, mais ne les supprime pas. Si votre objectif est d’afficher un site Web, un navigateur sera une option plus sécurisée.
13. Désactiver ou limiter la navigation
Si votre application n'a pas besoin de naviguer ou a seulement besoin de naviguer vers des pages connues, il sera de bon ton de restreindre la navigation à celles-ci et en interdisant tout autre type de navigation.
Pourquoi ?
La navigation est un vecteur d'attaque courant. Si un attaquant peut persuader votre application de naviguer loin de sa page actuelle, ils peuvent éventuellement forcer votre application à ouvrir d'autres sites web sur Internet. Même si vos webContents
sont configurés pour être plus sécurisé (comme avoir nodeIntegration
désactivé ou contextIsolation
activé), l'ouverture d'un site web aléatoire rendra le travail d'exploiter votre application beaucoup plus aisé.
Un modèle d'attaque courant est que l'attaquant pousse les utilisateurs de votre application à interagir avec l'application de manière à naviguer vers l'une des pages de l'attaquant. Cela se fait généralement par le biais de liens, de plugins, ou d'autres contenus générés par l'utilisateur.
Comment ?
If your app has no need for navigation, you can call event.preventDefault()
in a will-navigate
handler. Si vous savez vers quelles pages votre application peut naviguer, vérifiez l'URL dans le gestionnaire d'événements et laissez seulement la navigation se produire si elle correspond aux URL que vous attendez.
Nous vous recommandons d'utiliser l'analyseur de Node pour les URL. Des comparaisons simples de chaînes de caractères peuvent parfois être leurées - un test startsWith('https://example.com')
laisserait passer https://example.com.attacker.com
à travers.
const { URL } = require('url')
const { app } = require('electron')
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. Désactiver ou limiter la création de nouvelles fenêtres
Si vous avez un ensemble connu de fenêtres, il est bon de limiter la création de fenêtres supplémentaires dans votre application.
Pourquoi ?
Tout comme la navigation, la création de nouveaux webContents
est un vecteur d'attaque courant. . Les attaquants tentent de convaincre votre application de créer de nouvelles fenêtres, frames, ou autres processus de rendu avec des privilèges supplémentaires; ou avec des pages ouvertes qu'ils ne pouvaient pas ouvrir avant.
Si vous n'avez pas besoin de créer de nouvelles fenêtres en plus de celles que vous connaissez, la désactivation de la création vous permet d'obtenir sans frais un peu de sécurité supplémentaire. C'est généralement le cas pour les applications qui ouvrent une BrowserWindow
et n'ont pas besoin d'ouvrir un nombre arbitraire de fenêtres supplémentaires à l'exécution.
Comment ?
webContents
will delegate to its window open handler before creating new windows. Ce gestionnaire recevra , entre autres paramètres, l'url
demandée par la fenêtre et les options utilisées pour la créer. Nous vous recommandons d'enregistrer un gestionnaire pour surveiller la création de fenêtres et de refuser toute création inattendue de fenêtres.
const { app, shell } = require('electron')
app.on('web-contents-created', (event, contents) => {
contents.setWindowOpenHandler(({ url }) => {
// Dns cet exemple nous allons demander à l'Os
// d'ouvrir dans le navigateur par défaut l'url de l'événement.
//
// Voir l'élément suivant pour des considérations concernant ce que
// les URLs devraient être autorisées à travers shell.openExternal.
if (isSafeForExternalOpen(url)) {
setImmediate(() => {
shell.openExternal(url)
})
}
return { action: 'deny' }
})
})
15. Ne pas utiliser shell.openExternal
avec un contenu non fiable
The shell module's openExternal
API allows opening a given protocol URI with the desktop's native utilities. Sur macOS, par exemple, cette fonction est similaire à la commande open
du terminal et ouvrira l'application spécifique basée sur l'URI et en association avec le type du fichier.
Pourquoi ?
Improper use of openExternal
can be leveraged to compromise the user's host. Lorsque openExternal est utilisé avec du contenu non fiable, il peut être exploité pour exécuter des commandes arbitraires.
Comment ?
// Mauvais
const { shell } = require('electron')
shell.openExternal(USER_CONTROLLED_DATA_HERE)
// Bon
const { shell } = require('electron')
shell.openExternal('https://example.com/index.html')
16. Utiliser une version actuelle d'Electron
Vous devriez toujours vous efforcer d'utiliser la dernière version disponible d'Electron. Chaque fois qu'une nouvelle version majeure est publiée, vous devriez essayer de mettre à jour votre application le plus rapidement possible.
Pourquoi ?
Une application construite avec une ancienne version d'Electron, de Chromium ou de Node.js est une cible plus facile qu'une application qui utilise des versions plus récentes de ces composants. De manière générale, les problèmes de sécurité et les exploitation de failles pour les anciennes versions de Chromium et de Node.js sont plus fréquentes.
Chromium et Node.js représentent des prouesses impressionnantes d'ingénierie produites par des milliers de développeurs talentueux. Compte tenu de leur popularité, leur sécurité est soigneusement testée et analysée par des chercheurs en sécurité tout aussi compétents. Many of those researchers disclose vulnerabilities responsibly, which generally means that researchers will give Chromium and Node.js some time to fix issues before publishing them. Votre application sera plus sécurisée si elle exécute une version récente d'Electron (et donc Chromium et Node.js) dont les problèmes de sécurité potentiels ne sont pas aussi connus.
Comment ?
Migrez votre application d'une seule version majeure à la fois, tout en vous référant au document Changements majeurs avec rupture de compatibilité pour voir si du code doit être mis à jour.
17. Valider les sender
de tous les messages IPC
Vous devez toujours valider la propriété sender
des messages IPC entrants afin de vous assurer de ne pas effectuer d’actions sur des moteurs de rendu non approuvés ou de leur envoyer des informations.
Pourquoi ?
Tous les frames Web peuvent en théorie envoyer des messages IPC au processus principal, y compris des iframes et des fenêtres enfants dans certains scénarios. Si vous avez un message IPC retournant des données utilisateur à l’expéditeur via event.reply
ou effectuant des actions privilégiées ne pouvant être réalisées nativement par le moteur de rendu, vous devez alors vous assurer de ne pas être à l'écoute de frames tierces.
Vous devez valider par défaut le sender
de tous les messages IPC .
Comment ?
// Mauvais
ipcMain.handle('get-secrets', () => {
return getSecrets()
})
// Correct
ipcMain.handle('get-secrets', (e) => {
if (!validateSender(e.senderFrame)) return null
return getSecrets()
})
function validateSender (frame) {
// Valoriser l'hôte de l'URL à l'aide d'un analyseur d'URL et d'une liste d'autorisations
if ((new URL(frame.url)).host === 'electronjs.org') return true
return false
}
18. Évitez l'utilisation du protocole file://
et préférez l'utilisation de protocoles personnalisés
Il vaut mieux servir des pages locales à partir d'un protocole personnalisé plutôt que du protocole file://
.
Pourquoi ?
Le protocole file://
possède plus de privilèges dans Electron que dans un navigateur web et même dans les navigateurs il est traité différemment des URL http/https. Using a custom protocol allows you to be more aligned with classic web url behavior while retaining even more control about what can be loaded and when.
Pages running on file://
have unilateral access to every file on your machine meaning that XSS issues can be used to load arbitrary files from the users machine. Using a custom protocol prevents issues like this as you can limit the protocol to only serving a specific set of files.
Comment ?
Follow the protocol.handle
examples to learn how to serve files / content from a custom protocol.
19. Vérifiez quels fuse vous pouvez modifier
Electron ships with a number of options that can be useful but a large portion of applications probably don't need. In order to avoid having to build your own version of Electron, these can be turned off or on using Fuses.
Pourquoi ?
Some fuses, like runAsNode
and nodeCliInspect
, allow the application to behave differently when run from the command line using specific environment variables or CLI arguments. These can be used to execute commands on the device through your application.
This can let external scripts run commands that they potentially would not be allowed to, but that your application might have the rights for.
Comment ?
We've made a module, @electron/fuses
, to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases, and refer to How do I flip the fuses? in our documentation.