Aller au contenu principal

Sécurité

Signaler des problèmes de 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.

danger

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 soit la balise <webview> soit une BrowserView et veillez à ce que nodeIntegration soit désactivée et que contextIsolation, lui, soit bien activé.

Avertissements de sécurité d'Electron

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:

  1. Charger uniquement du contenu sécurisé
  2. Désactiver l'intégration de Node.js dans tous les moteurs de rendu qui affichent du contenu distant
  3. Activer l’isolation de contexte dans tous les moteurs de rendu
  4. Activer le sandboxing de processus
  5. Utiliser session.setPermissionRequestHandler() dans toutes les sessions chargeant du contenu distant
  6. Ne pas désactiver webSecurity
  7. Définissez une Content-Security-Policy et utilisez des règles restrictives (c.-à-d. script-src 'self')
  8. Ne pas activer allowRunningInsecureContent
  9. Ne pas activer les fonctionnalités expérimentales
  10. Ne pas utiliser enableBlinkFeatures
  11. <webview> : N'utilisez pas allowpopups
  12. <webview>: Vérifier les options et les paramètres
  13. Désactiver ou limiter la navigation
  14. Désactiver ou limiter la création de nouvelles fenêtres
  15. Ne pas utiliser shell.openExternal avec un contenu non fiable
  16. Utiliser une version actuelle d'Electron
  17. Valider les sender de tous les messages IPC
  18. Évitez l'utilisation du protocole file:// et préférez l'utilisation de protocoles personnalisés
  19. 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. Pour plus de détails sur les faiblesses potentielles et les bogues d'implémentation lors du développement d'applications utilisant Electron, veuillez vous référer à ce guide pour développeurs et auditeurs.

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 :

  1. 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.
  2. 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 ?

main.js (Main Process)
// Incorrect
browserWindow.loadURL('http://example.com')

// Correct
browserWindow.loadURL('https://example.com')
index.html (Renderer Process)
<!-- 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

info

Cette recommandation correspond au comportement par défaut d'Electron depuis la version 5.0.0.

Il est primordial de ne pas activer l'intégration de Node.js dans tous les moteurs de rendu (BrowserWindow, BrowserView, ou <webview>) qui chargent du contenu distant. 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 ?

main.js (Main Process)
// Incorrect
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: false,
nodeIntegration: true,
nodeIntegrationInWorker: true
}
})

mainWindow.loadURL('https://example.com')
main.js (Main Process)
// Correct
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})

mainWindow.loadURL('https://example.com')
index.html (Renderer Process)
<!-- 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

info

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.

info

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é.

info

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 ?

main.js (Main Process)
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

info

Cette recommandation est la valeur par défaut d’Electron.

Vous avez peut-être déjà deviné que la désactivation de la propriété webSecurity sur un processus de rendu (BrowserWindow, BrowserView, ou <webview>) désactive des fonctionnalités de sécurité cruciales.

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 ?

main.js (Main Process)
// Incorrect
const mainWindow = new BrowserWindow({
webPreferences: {
webSecurity: false
}
})
main.js (Main Process)
// Correct
const mainWindow = new BrowserWindow()
index.html (Renderer Process)
<!-- 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 :

main.js (Main Process)
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> :

index.html (Renderer Process)
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">

8. Ne pas activer allowRunningInsecureContent

info

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 ?

main.js (Main Process)
// Incorrect
const mainWindow = new BrowserWindow({
webPreferences: {
allowRunningInsecureContent: true
}
})
main.js (Main Process)
// Correct
const mainWindow = new BrowserWindow({})

9. Ne pas activer les fonctionnalités expérimentales

info

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 ?

main.js (Main Process)
// Incorrect
const mainWindow = new BrowserWindow({
webPreferences: {
experimentalFeatures: true
}
})
main.js (Main Process)
// Correct
const mainWindow = new BrowserWindow({})

10. Ne pas utiliser enableBlinkFeatures

info

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 ?

main.js (Main Process)
// Mauvais
const mainWindow = new BrowserWindow({
webPreferences: {
enableBlinkFeatures: 'ExecCommandInJavaScript'
}
})
main.js (Main Process)
// Correct
const mainWindow = new BrowserWindow()

11. Ne pas utiliser allowpopups pour les WebViews

info

Cette recommandation correspond au comportement par défaut d’Electron.

Si vous utilisez <webview>, vous aurez peut-être besoin des pages et des scripts chargés dans votre balise <webview> pour ouvrir de nouvelles fenêtres. 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 ?

index.html (Renderer Process)
<!-- 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.

C'est une bonne idée de contrôler la création de nouvelles balises <webview> depuis le processus principal et de vérifier que leurs préférences web ne désactivent pas les fonctions de sécurité .

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. Dans la plupart des cas, les développeurs n'ont pas besoin de désactiver ces fonctionnalités - et vous ne devriez donc pas autoriser différentes configurations pour les balises <webview> nouvellement créées.

Comment ?

Avant qu'une tag <webview> ne soit attaché, Electron déclenchera l'événement will-attach-webview sur le webContents l'hébergeant. Utilisez l'événement pour empêcher la création de webViews avec des options potentiellement non sécurisées.

main.js (Main Process)
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 ?

Si votre application n'a pas besoin de navigation, vous pouvez appeler event.preventDefault() dans un gestionnaire de will-navigate. 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.

main.js (Main Process)
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 va mandater son windowOpenHandler pour intervenir avant la création de nouvelles fenêtres. 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.

main.js (Main Process)
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

L’API openExternal du module shell permet d’ouvrir une URI d'un protocole donné avec les utilitaires natifs du bureau. 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 ?

L'utilisation incorrecte de openExternal peut être utilisée pour compromettre l'hôte de l'utilisateur. Lorsque openExternal est utilisé avec du contenu non fiable, il peut être exploité pour exécuter des commandes arbitraires.

Comment ?

main.js (Main Process)
// Mauvais
const { shell } = require('electron')
shell.openExternal(USER_CONTROLLED_DATA_HERE)
main.js (Main Process)
// 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. Beaucoup de ces chercheurs révèlent des vulnérabilités de manière responsable, ce qui signifie généralement que les chercheurs donnent de leur temps à Chromium et Node.js pour résoudre les problèmes avant de les publier. 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 ?

main.js (Main Process)
// 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.