Two builds of NotesDesk, a small Electron app written for these examples. Both were read statically; neither was run. Open a place to see the lines it was read from.
main.js::win nodeIntegrationInEffect on → off less permissivemain.js::win sandboxInEffect off → on less permissiveWhether a change matters depends on what the window loads. This is a fact to review, not a verdict.
interfacespreload.js::notesdesk::checkUpdate link directpreload.js:96 listNotes: () => ipcRenderer.invoke("notes:list"),7 saveNote: (note) => ipcRenderer.invoke("notes:save", note),8 quit: () => ipcRenderer.send("app:quit"),9 checkUpdate: () => ipcRenderer.invoke("update:check"),10});11
main.js:3027ipcMain.handle("notes:list", () => store.get("notes") ?? []);28ipcMain.handle("notes:save", (_e, note) => store.push("notes", note));29ipcMain.on("app:quit", () => app.quit());30ipcMain.handle("update:check", async () => fetch("https://updates.notesdesk.example/latest.json").then((r) => r.json()));31// The channel name comes from the environment at run time, so no static reading can name it.32for (const plugin of (process.env.NOTESDESK_PLUGINS ?? "").split(",").filter(Boolean))33 ipcMain.handle(`plugin:${plugin}`, () => store.get(`plugins.${plugin}`));
preload.js::notesdesk::openInShell link directpreload.js:96 listNotes: () => ipcRenderer.invoke("notes:list"),7 saveNote: (note) => ipcRenderer.invoke("notes:save", note),8 quit: () => ipcRenderer.send("app:quit"),9 openInShell: (target) => ipcRenderer.send("shell:open", target),10});11
main.js:3027ipcMain.handle("notes:list", () => store.get("notes") ?? []);28ipcMain.handle("notes:save", (_e, note) => store.push("notes", note));29ipcMain.on("app:quit", () => app.quit());30ipcMain.on("shell:open", (_e, target) => shell.openPath(target));31 32app.whenReady().then(createWindow);33app.on("window-all-closed", () => app.quit());
contextBridgenotesdesk::checkUpdatepreload.js:96 listNotes: () => ipcRenderer.invoke("notes:list"),7 saveNote: (note) => ipcRenderer.invoke("notes:save", note),8 quit: () => ipcRenderer.send("app:quit"),9 checkUpdate: () => ipcRenderer.invoke("update:check"),10});11
notesdesk::openInShellpreload.js:96 listNotes: () => ipcRenderer.invoke("notes:list"),7 saveNote: (note) => ipcRenderer.invoke("notes:save", note),8 quit: () => ipcRenderer.send("app:quit"),9 openInShell: (target) => ipcRenderer.send("shell:open", target),10});11
ipcChannelsupdate:checkmain.js:3027ipcMain.handle("notes:list", () => store.get("notes") ?? []);28ipcMain.handle("notes:save", (_e, note) => store.push("notes", note));29ipcMain.on("app:quit", () => app.quit());30ipcMain.handle("update:check", async () => fetch("https://updates.notesdesk.example/latest.json").then((r) => r.json()));31// The channel name comes from the environment at run time, so no static reading can name it.32for (const plugin of (process.env.NOTESDESK_PLUGINS ?? "").split(",").filter(Boolean))33 ipcMain.handle(`plugin:${plugin}`, () => store.get(`plugins.${plugin}`));
preload.js:96 listNotes: () => ipcRenderer.invoke("notes:list"),7 saveNote: (note) => ipcRenderer.invoke("notes:save", note),8 quit: () => ipcRenderer.send("app:quit"),9 checkUpdate: () => ipcRenderer.invoke("update:check"),10});11
shell:openmain.js:3027ipcMain.handle("notes:list", () => store.get("notes") ?? []);28ipcMain.handle("notes:save", (_e, note) => store.push("notes", note));29ipcMain.on("app:quit", () => app.quit());30ipcMain.on("shell:open", (_e, target) => shell.openPath(target));31 32app.whenReady().then(createWindow);33app.on("window-all-closed", () => app.quit());
preload.js:96 listNotes: () => ipcRenderer.invoke("notes:list"),7 saveNote: (note) => ipcRenderer.invoke("notes:save", note),8 quit: () => ipcRenderer.send("app:quit"),9 openInShell: (target) => ipcRenderer.send("shell:open", target),10});11
windowsmain.js::winnodeIntegration true → falsenodeIntegrationInEffect "on" → "off"sandbox false → truesandboxInEffect "off" → "on"main.js:85const store = new Store(path.join(app.getPath("userData"), "settings.json"));6 7function createWindow() {8 const win = new BrowserWindow({9 width: 1100,10 height: 720,11 webPreferences: {
webPreferencesmain.js::win::nodeIntegrationvalue true → falsemain.js:1411 webPreferences: {12 preload: path.join(__dirname, "preload.js"),13 contextIsolation: true,14 nodeIntegration: false,15 sandbox: true,16 },17 });
main.js::win::sandboxvalue false → truemain.js:1512 preload: path.join(__dirname, "preload.js"),13 contextIsolation: true,14 nodeIntegration: false,15 sandbox: true,16 },17 });18 win.loadFile("renderer/index.html");
endpointsmain.js::fetch::https://updates.notesdesk.example/latest.json literalmain.js:3027ipcMain.handle("notes:list", () => store.get("notes") ?? []);28ipcMain.handle("notes:save", (_e, note) => store.push("notes", note));29ipcMain.on("app:quit", () => app.quit());30ipcMain.handle("update:check", async () => fetch("https://updates.notesdesk.example/latest.json").then((r) => r.json()));31// The channel name comes from the environment at run time, so no static reading can name it.32for (const plugin of (process.env.NOTESDESK_PLUGINS ?? "").split(",").filter(Boolean))33 ipcMain.handle(`plugin:${plugin}`, () => store.get(`plugins.${plugin}`));
storagerenderer/app.bundle.js::localStorage::notesdesk.telemetry::read literalrenderer/app.bundle.js:1512 return res.json();13}14async function telemetry(event) {15 if (localStorage.getItem("notesdesk.telemetry") !== "on") return;16 await fetch("https://telemetry.notesdesk.example/collect", { method: "POST", body: JSON.stringify({ event, ts: Date.now() }) });17}18/***/ }),
urlsmain.js::https://updates.notesdesk.example/latest.json literalmain.js:3027ipcMain.handle("notes:list", () => store.get("notes") ?? []);28ipcMain.handle("notes:save", (_e, note) => store.push("notes", note));29ipcMain.on("app:quit", () => app.quit());30ipcMain.handle("update:check", async () => fetch("https://updates.notesdesk.example/latest.json").then((r) => r.json()));31// The channel name comes from the environment at run time, so no static reading can name it.32for (const plugin of (process.env.NOTESDESK_PLUGINS ?? "").split(",").filter(Boolean))33 ipcMain.handle(`plugin:${plugin}`, () => store.get(`plugins.${plugin}`));
ipc_channel_unresolvednpx hexvero demo
npx hexvero compare hexvero-demo/notesdesk-1.4.0.asar hexvero-demo/notesdesk-1.5.0.asar --report report.md
npx hexvero ui --demo --open
The Markdown report of this comparison: report.md.