Closed raphael10-collab closed 9 months ago
Hi @jjeff !
In this repo: https://github.com/raphael10-collab/bytenode-contextIsolationTrue-electron-forge-typescript-webpack
you can see that I've set nodeIntegration
to false
, and contextIsolation
to true
As you explained here: https://github.com/herberttn/bytenode-webpack-plugin/issues/29#issuecomment-1702995183 Bytenode always require Node to work.
If I want to keep for good electron safety practice - https://www.electronjs.org/docs/latest/tutorial/security - nodeIntegration
to false
, and contextIsolation
to true
, you suggest me to have all Bytenode compiled code in the preload scripts, because preload scripts have access to the renderer scope.
I've set up my preload.ts script as follows:
console.log('💃 hello from preload')
// https://www.electronjs.org/docs/latest/tutorial/ipc
const {
contextBridge,
ipcRenderer,
shell,
webFrame
} = require("electron")
export {}
declare global {
interface Window {
//setupRenderer,
api: {
send: (channel: string, ...arg: any) => void;
receive: (channel: string, func: (event: any, ...arg: any) => void) => void;
// https://github.com/frederiksen/angular-electron-boilerplate/blob/master/src/preload/preload.ts
// https://www.electronjs.org/docs/all#ipcrenderersendtowebcontentsid-channel-args
electronIpcSendTo: (window_id: string, channel: string, ...arg: any) => void;
electronIpcSend: (channel: string, ...arg: any) => void;
giveMeAStream: (eventId: string) => void;
electronIpcOn: (channel: string, listener: (event: any, ...arg: any) => void) => void;
electronIpcSendSync: (channel: string, ...arg: any) => void;
// https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererinvokechannel-args
electronIpcInvoke: (channel: string, ...arg: any) => void;
// https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererpostmessagechannel-message-transfer
electronIpcPostMessage: (channel: string, message: any, transfer?: MessagePort[]) => void;
electronIpcOnce: (channel: string, listener: (event: any, ...arg: any) => void) => void;
electronIpcRemoveListener: (channel: string, listener: (event: any, ...arg: any) => void) => void;
electronIpcRemoveAllListeners: (channel: string) => void;
setFullscreen: (flag: any) => void;
};
attachEvent(event: string, listener: EventListener): boolean;
detachEvent(event: string, listener: EventListener): void;
// https://www.electronjs.org/docs/latest/tutorial/context-isolation#usage-with-typescript
bwScrollAPI: {
getScrollAmount: () => void;
}
}
}
contextBridge.exposeInMainWorld(
"api", {
// https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererpostmessagechannel-message-transfer
electronIpcPostMessage: (channel: string, message: any, transfer?: MessagePort[]) => {
ipcRenderer.postMessage(channel, message, transfer)
},
send: (channel: any, data: any) => {
console.log("preload-send called: args: ", data);
ipcRenderer.invoke(channel, data).catch(e => console.log(e))
},
receive: (channel: any, func: any) => {
console.log("preload-receive called. args: ");
ipcRenderer.on(channel, (event, ...args) => func(...args));
},
// https://www.electronjs.org/docs/all#ipcrenderersendtowebcontentsid-channel-args
electronIpcSendTo: (window_id: number, channel: string, ...arg: any) => {
ipcRenderer.sendTo(window_id, channel, arg);
},
// https://github.com/frederiksen/angular-electron-boilerplate/blob/master/src/preload/preload.ts
electronIpcSend: (channel: string, ...arg: any) => {
ipcRenderer.send(channel, arg);
},
giveMeAStream: (eventId: string) => {
ipcRenderer.send('give-me-a-stream', eventId)
},
electronIpcSendSync: (channel: string, ...arg: any) => {
return ipcRenderer.sendSync(channel, arg);
},
// https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererinvokechannel-args
electronIpcInvoke: (channel: string, ...arg: any) => {
return ipcRenderer.invoke(channel, ...arg)
},
electronIpcOn: (channel: string, listener: (event: any, ...arg: any) => void) => {
ipcRenderer.on(channel, listener);
},
electronIpcOnce: (channel: string, listener: (event: any, ...arg: any) => void) => {
ipcRenderer.once(channel, listener);
},
electronIpcRemoveListener: (channel: string, listener: (event: any, ...arg: any) => void) => {
ipcRenderer.removeListener(channel, listener);
},
electronIpcRemoveAllListeners: (channel: string) => {
ipcRenderer.removeAllListeners(channel);
},
setFullscreen: (flag: string) => {
ipcRenderer.invoke('setFullscreen', flag);
},
},
)
What should I practically add to the above preload.ts
code in order to have my all Bytonode compiled code within preload.ts
?
You might want to play with https://github.com/spaceagetv/electron-bytenode-example and try different configurations in a simplified environment. I have yet to implement Electron security best practices in that repo, but I think it can be done. In most of my applications, I'm not loading untrusted web pages into my renderers, so I'm okay without context isolation enabled.
What should I practically add to the above preload.ts code in order to have my all Bytonode compiled code within preload.ts ?
I don't know if there's anything you need to add to the preload script to compile it with Bytenode. You just need to configure webpack to compile preload scripts.
If you're asking if it's possible to move your renderer script code into your preload script so that it will be compiled, the answer is usually "yes". The main trick is to use the DOMContentLoaded
event to keep your DOM-interacting code from running before the DOM has been loaded.
I've set nodeIntegration
to false
and contextIsolation
to true
And
I've configured webpack
to compile preload scripts, I've set the plugins in webpack
config, specifying the compileForElectron
flag, and I've tried to put inside the preload
this example code: https://github.com/spaceagetv/electron-bytenode-example/blob/main/src/renderer/preload.ts.
But it does not work
I've updated the repo in github: https://github.com/raphael10-collab/bytenode-contextIsolationTrue-electron-forge-typescript-webpack.git to contain all these aforementioned trials
So, I guess there is something missing, in order to make bytenode
work with the Electron security best practices in place,
with nodeIntegration
to false
and contextIsolation
to true
as fixed landmarks
@jjeff
setting :
contextIsolation: false,
nodeIntegration: true,
sandbox: false,
yields this error : Cannot find module `v8`
I've updated the repo in github: https://github.com/raphael10-collab/bytenode-contextIsolationTrue-electron-forge-typescript-webpack.git to contain all these aforementioned trials
The best would be to be able to set
contextIsolation: true,
nodeIntegration: false,
while being able to use bytenode-webplack-plugin
Just my two cents; I've spent a few weeks this year (yes... full time 😅) trying to get bytenode to work with nodeIntegration
off, but was unable to get it to work.
What did work was to make a fork of bytenode that strips the 'encoding' bits from the library, and only leave the decoding bits.
This is done in electron-vite as well, and in the end I migrated from webpack to vite so as to not manage all this myself.
Duplicate of #28
I git cloned and started https://github.com/herberttn/bytenode-webpack-plugin/tree/main/examples/electron-forge-typescript-webpack
I tried to change the
contextIsolation
and thenodeIntegration
settings respectively totrue
andfalse
:with
preload.ts
:But, after this change, I get this error:
unable to load preload script
what am I missing ? How to make it work?