Aller au contenu principal

Isolation du contexte

Qu'est-ce que c'est ?

L'isolement du contexte est une fonctionnalité qui garantit l'exécution dans des contextes différents de vos scripts preload avec la logique interne d'Electron et du site Web que vous chargez dans un webContents. Ceci est important pour des raisons de sécurité car cela va empêcher le site Web d'accéder aux fonctionalités d'Electron ou aux API puissantes auxquelles votre script preload a accès.

Cela signifie entre autres que l'objet window auquel votre script de préchargement (preload) a accès est un objet différent de celui auquel le site Web peut accéder. Par exemple, si vous définissez window.hello = 'wave' dans votre script de préchargement et que l’isolation du contexte est activée, window.hello retournera undefined si le site Web tente d’y accéder.

L'isolation du contexte est activée par défaut depuis Electron 12, et c'est un paramètre de sécurité recommandé pour toutes les applications.

Migration

Sans isolation du contexte, j’avais l’habitude de fournir des API à partir de mon script de préchargement à l’aide de window.X = apiObject. Et maintenant, comment dois je faire?

Avant: isolation du contexte désactivée

Un cas d’utilisation courant est d'exposer à un site Web chargé dans un processus de rendu, une API à partir de votre script de préchargement. Lorsque l’isolation contextuelle est désactivée, votre script de préchargement partage un objet window global commun avec le moteur de rendu. Vous pouvez donc dans ce cas attacher n'importe quelle propriété à un script de préchargement:

preload.js
// préchargement avec isolation du contexte désactivé
window.myAPI = {
doAThing: () => {}
}

Dans ce cas la fonction doAThing() peut être utilisée directement dans le processus de rendu :

renderer.js
//utilisation dans le moteur de rendu de l’API exposée 
window.myAPI.doAThing()

Après: isolation du contexte activée

Un module spécifique d'Electron est là pour vous aider à la réalisation de cette isolation. The contextBridge module can be used to safely expose APIs from your preload script's isolated context to the context the website is running in. L'API restera comme avant, accessible depuis le site web en utilisant window.myAPI.

preload.js
// préchargement avec isolatiçon du contexte activé
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
doAThing: () => {}
})
renderer.js
//utilisation dans le moteur de rendu de l’API exposée 
window.myAPI.doAThing()

Afin de bien comprendre les limites de celui-ci, nous vous conseillons de lire la documentation de contextBridge dont le lien est indiqué ci-dessus. Par exemple, vous ne pouvez pas l'utiliser pour envoyer des prototypes ou des symboles.

Mesures de sécurité

L'activation de contextIsolation et l'utilisation de contextBridge ne signifie pas automatiquement que tout ce que vous faites est sans danger. Par exemple, le code suivant est dangereux.

preload.js
// ❌ Code dangereux
contextBridge.exposeInMainWorld('myAPI', {
send: ipcRenderer.send
})

C'est effectivement dangereux car le code expose directement une API puissante sans aucun fitrage sur les arguments. Cela pourrait permettre à n’importe quel site Web d’envoyer des messages IPC arbitraires et bien sur, ce n'est absolument pas ce que vous souhaitez. La bonne façon d’exposer les API basées sur les IPC est plutôt de fournir une méthode par message IPC.

preload.js
// ✅ Code sécurisé
contextBridge.exposeInMainWorld('myAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})

Utilisation avec TypeScript

Si vous créez votre application Electron en utilisant TypeScript, vous aurez probablement besoin d'ajouter des types à vos API exposées via le contextBridege. L’objet window du moteur de rendu n’aura les typages leurs correspondant que si vous étendez les types avec un fichier de déclaration .

Par exemple, avec un tel script preload.ts:

preload.ts
contextBridge.exposeInMainWorld('electronAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})

Vous pouvez créer un fichier de déclaration interface.d.ts et enrichir globalement l’interface Window :

interface.d.ts
export interface IElectronAPI {
loadPreferences: () => Promise<void>,
}

declare global {
interface Window {
electronAPI: IElectronAPI
}
}

En procédant ainsi vous vous assurez que le compilateur TypeScript aura connaissance de la propriété electronAPI de votre objet global window lors de son utilisation dans les scripts dans votre processus de rendu :

renderer.ts
window.electronAPI.loadPreferences()