0
votes

I'm building an App (Electron based) where I need to get an information from a third party website before the main window is created, but I'm a little bit confused about security measures. I'm using axios to do the HTTP request inside the main process because it is promise based and I can create the window after the website is fetched. My concerns are:

Enabling nodeIntegration is not good when messing with the renderer process because of cross-site-scripting attack. Should I include all nodejs modules in a preload.js like the following, for example.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="script-src 'self';">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Viewer</title>
</head>
<body>
    <div id="box">
        <form id='fo'>
                <input type="text" id="num">
                <button type="button" id="bttn">Random</button>
        </form>
    </div>
    <script src="renderer.js"></script>
</body>
</html>

main.js

const electron = require('electron');
const cheerio = require('cheerio');
const axios = require('axios').default;
const path = require('path');
const {app, BrowserWindow, ipcMain, Menu, MenuItem,session} = electron;

let win;
let url = 'sampletext';

function createWindow() {
    win = new BrowserWindow({
        width: 400,
        height: 250,
        webPreferences:{
            nodeIntegration: false,
            contextIsolation: true,
            preload: path.join(app.getAppPath(), 'preload.js')
        },
        show: false,                        
    });

    win.loadFile('index.html');

    win.once('ready-to-show', () =>{
        win.show();
    });

    win.on('closed', () =>{
        win = null;
    });
}

app.whenReady().then(getRequest().then(res => {
    const $ = cheerio.load(res);
    if($('infoNeeded')){
        random = get_numbers($('infoNeeded').attr('href'));
    }
    createWindow();
}));

app.on('window-all-closed', () =>{
    app.quit();
});

function getRequest() {
    return axios.get(url).then(res =>  res.data).catch(err => console.log(err));
}

preload.js

//Instead of using getRequest() on main.js use this file
const electron = require('electron');
const remote = require('electron').remote;
const cheerio = require('cheerio');
const axios = require('axios').default;
let url = 'sampletext';

//So I can use it in renderer.js
window.getReq = function () {
    return axios.get(url).then(res =>  res.data).catch(err => console.log(err));
}

window.parseInfo = function (data) {
    const $ = cheerio.load(data);
    if($('infoNeeded')){
       return random = get_numbers($('infoNeeded').attr('href'));
    }
    return;
}

//Preload first request
window.getReq().then(doStuffHere);

renderer.js

let info;

//Keep updating the info

setInterval( () =>{
    window.getReq().then(data => {
        info = window.parseInfo(data);
    });
}, 10000);

1) Is it ok to do nodejs require inside main process? If not, what's the secure way of doing it?

2) May I make HTTP requests inside main process? If yes, should I send a CSP header when doing so?

3) Instead of doing the request inside the main.js, should I use "webPreferences: preload" property and make the first HTTP request inside preload.js (Just like the above example) ? (I need to get the info before sending it to renderer.js)

I've already read https://www.electronjs.org/docs/tutorial/security, but I couldn't grasp their teaching. If you could provide an answer for how and when to use preload.js and CSP header I'll be very grateful.

1
At the very least use ES modules, so your code doesn't execute until its dependencies are loaded, and use the defer attribute on your <script> elements. - Mike 'Pomax' Kamermans

1 Answers

0
votes
  1. Yes it is ok to use node.js require in the main process(use any library with error handling, cause it may crash the app)
  2. You can make an HTTP request from the main process
  3. You can use Preload.js if you need the code execution result in the renderer process.(You can also use the ipc)