Die Sandbox ist ein Sicherheits-Feature von Chromium, das Electron für Renderer-Prozesse nutzt: der Prozess läuft mit eingeschränkten OS-Berechtigungen und kann auch im Preload kein direktes Node-API mehr aufrufen. Default seit Electron 20, sollte fast immer aktiv bleiben.

Aktivierung

JavaScript
const win = new BrowserWindow({
    webPreferences: {
        preload: path.join(__dirname, 'preload.js'),
        sandbox: true,         // explizit (Default seit v20)
        contextIsolation: true,
        nodeIntegration: false
    }
});

sandbox: true aktiviert die Sandbox für den Renderer und das Preload-Skript dieses Fensters.

Was die Sandbox einschränkt

Im Sandbox-Modus hat der Renderer-Prozess (und sein Preload):

BereichErlaubtVerboten
FilesystemÜber IPC zum MainKein direktes fs
Child-ProcessÜber IPCKein child_process
Native ModulesNeinAuch nicht im Preload
OS-CallsNur via Chromium-APIKeine direkten Syscalls
Web-APIsVoll
electron-ModulNur contextBridge, ipcRenderer, webFrameRest weg
process-Variableversions, platform, arch, pidprocess.env, cwd() etc.

Praktisch: jede Native-Operation läuft jetzt über IPC. Der Main hat den vollen Node-Zugriff und delegiert kontrolliert.

Warum das gut ist

Die Sandbox kombiniert zwei Sicherheits-Ebenen:

  1. JavaScript-Ebene: Preload kann keine Node-APIs mehr direkt aufrufen → kompromittierter Web-Code kann das auch nicht
  2. OS-Ebene: der Renderer-Prozess läuft mit reduzierten Berechtigungen — selbst bei einer Chromium-Schwachstelle kann der Angreifer das System nicht direkt manipulieren

Faustregel: ohne Sandbox bist du allein mit JavaScript-Mauern; mit Sandbox stehst du auf zwei Beinen.

Workflow mit Sandbox

Der typische Workflow im Sandbox-Modus:

JavaScript preload.js — schlanke Bridge
import { contextBridge, ipcRenderer } from 'electron';

contextBridge.exposeInMainWorld('api', {
    readFile:  (p) => ipcRenderer.invoke('files:read', p),
    writeFile: (p, c) => ipcRenderer.invoke('files:write', p, c),
    execCmd:   (cmd) => ipcRenderer.invoke('shell:exec', cmd)
});
JavaScript main.js — die schwere Logik
import fs from 'node:fs/promises';
import { execFile } from 'node:child_process';

ipcMain.handle('files:read', async (_event, path) => {
    // Validierung!
    if (!path.startsWith(app.getPath('userData'))) return null;
    return fs.readFile(path, 'utf-8');
});

ipcMain.handle('shell:exec', async (_event, cmd) => {
    // Whitelisting!
    const allowed = ['ls', 'pwd'];
    if (!allowed.includes(cmd)) return null;
    return new Promise((res) => execFile(cmd, [], (_e, out) => res(out)));
});

Der Preload ist eine dünne Bridge ohne Logik. Die echte Arbeit (mit Validierung) passiert im Main.

Wann Sandbox deaktivieren?

Realistisch gibt es zwei Szenarien:

  1. Legacy-Migration: alte Apps, die im Preload Node-APIs nutzen — Übergangsweise mit sandbox: false, bis die Logik in den Main migriert ist.
  2. Sehr spezifische Use-Cases: z. B. Browser-Erweiterungen, die intern Node nutzen müssen, ohne IPC-Roundtrip — sehr selten.

In allen anderen Fällen: aktiviert lassen. Die paar IPC-Calls mehr lohnen sich für das Sicherheits-Plus.

Sandbox + ESM

Seit Electron 28 funktioniert ESM auch im Sandbox-Preload. Vor 28: nur CommonJS. Wer also ein altes Projekt hochzieht und ESM-Preload haben will:

JSON package.json
{
  "type": "module"
}

Plus Electron ≥ 28. Beides zusammen → moderne ESM-Syntax, volle Sandbox-Sicherheit.

FAQ

Ist Sandbox automatisch an?

Seit Electron 20 ist sandbox: true der empfohlene Default — bei explizitem webPreferences muss man's aber selbst setzen. Wer ohne webPreferences-Block ein Window erzeugt: Sandbox ist nicht automatisch an. Daher immer explizit angeben.

Was ist der Unterschied zu contextIsolation?

contextIsolation trennt Preload- und Web-Heap (JavaScript-Ebene). Sandbox läuft den Renderer in eingeschränkten OS-Berechtigungen (Prozess-Ebene) UND limitiert die Node-APIs im Preload. Beide sind separate Schutz-Layer — gemeinsam genutzt.

Welche electron-Imports gehen im Sandbox-Preload?

contextBridge, ipcRenderer, webFrame. Mehr nicht. Wer dialog, app etc. braucht: das geht nur im Main, der Preload muss per IPC delegieren.

Bricht Sandbox bestehende Web-Apps?

Nein — Web-APIs (DOM, fetch, localStorage etc.) funktionieren komplett. Was bricht: Code, der direkt require('fs') o. ä. im Renderer aufrief (was schon vor Sandbox keine gute Idee war).

Wie performant ist Sandbox?

Praktisch nicht messbar. IPC-Roundtrips kosten Mikrosekunden. In Hot-Paths mit zehntausenden Calls pro Sekunde könnte's auffallen — bei normalen Apps nicht.

Funktioniert Sandbox auf allen Plattformen gleich?

Auf Linux setzt Chromium auf das unprivileged_userns_clone-Feature. Auf manchen alten Distros oder unter bestimmten Container-Setups (Docker ohne --cap-add SYS_ADMIN) kann die Sandbox stören oder gar nicht starten. Pragmatisch: testen, dann ggf. mit --no-sandbox umgehen — für Distribution aber niemals.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Renderer & Preload

Zur Übersicht