Security and quality
Keep secure window defaults
Review the BrowserWindow boundary and understand what context isolation, sandboxing, and disabled Node integration protect.
We set three security options when we created the window. Now that the app works, let’s go back and understand what each one protects. Every window is a separate security decision, so this review applies to any BrowserWindow you add later.
webPreferences: {
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
contextIsolation: true,
nodeIntegration: false,
sandbox: true
}
What each option does
nodeIntegration: false keeps Node.js out of page code. Without it, require('node:fs') works from the renderer, and any script injected into the page can read and delete files.
contextIsolation: true gives the preload script its own JavaScript world. The page can’t reach into the preload’s variables or overwrite contextBridge. It sees only what we expose on window.notesAPI.
sandbox: true puts the renderer in Chromium’s OS-level sandbox, the same one that protects browser tabs. Even if an exploit escapes JavaScript, the process itself has very little power.
Current Electron releases already default to context isolation and a sandboxed renderer. I still write them out. Defaults change between versions, and a generated config can hide an override. An explicit value is visible in code review.
The temptation
At some point an import will fail in the renderer or the preload, and a Stack Overflow answer will tell you to set nodeIntegration: true or sandbox: false. Don’t.
If the renderer needs an npm package, bundle a browser-compatible one through Webpack. If it needs a file or a native Electron API, add one validated preload method and do the work in the main process.
And never load remote content into a window that has Node integration. Remote content changes outside your release process. You’d be handing filesystem access to whoever controls that server.
Adjacent controls
These three flags are not the whole story. Also confirm that:
webSecurityis still enabled- mixed content (HTTP resources on an HTTPS page) is not allowed
- experimental Blink features are off
- the page has the restrictive Content Security Policy from
index.html - navigation, new windows, and permissions are controlled (the next two lessons)
Test the boundary
Open DevTools in the renderer and type require('node:fs'). You should get ReferenceError: require is not defined. Then type window.notesAPI.loadNotes and confirm it’s a function. Expand window.notesAPI and check that no raw Electron object, like ipcRenderer, is in there.
One last point. These options limit damage. They don’t make renderer input trusted. The sender check and the validator in the main process are still necessary.
Lesson completed