Skip to content

Commit aef9303

Browse files
authored
[DevTools] upgrade electron to latest version & security improvements (#26337)
## Summary resolves #25667 This PR also resolves several security issues in the standalone app ## How did you test this change? Tested locally `yarn start` in react-devtools package. Everything works normal --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1204123419819195
1 parent 161f6ae commit aef9303

File tree

5 files changed

+80
-140
lines changed

5 files changed

+80
-140
lines changed

packages/react-devtools/app.html

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -156,28 +156,11 @@
156156
</div>
157157
</div>
158158
<script>
159-
const fs = require('fs');
160-
let options;
161-
let useHttps = false;
159+
// window.api is defined in preload.js
160+
const {electron, readEnv, ip, getDevTools} = window.api;
161+
const {options, useHttps, host, protocol, port} = readEnv();
162162

163-
try {
164-
if (process.env.KEY && process.env.CERT) {
165-
options = {
166-
key: fs.readFileSync(process.env.KEY),
167-
cert: fs.readFileSync(process.env.CERT)
168-
};
169-
useHttps = true;
170-
}
171-
} catch (err) {
172-
console.error('Failed to process SSL options - ', err);
173-
options = undefined;
174-
}
175-
176-
const {clipboard} = require("electron");
177-
const host = process.env.HOST || 'localhost';
178-
const protocol = useHttps ? 'https' : 'http';
179-
const port = Number(process.env.PORT || 8097);
180-
const localIp = require("ip").address();
163+
const localIp = ip.address();
181164
const defaultPort = (port === 443 && useHttps) || (port === 80 && !useHttps);
182165
const server = defaultPort ? `${protocol}://${host}` : `${protocol}://${host}:${port}`;
183166
const serverIp = defaultPort ? `${protocol}://${localIp}` : `${protocol}://${localIp}:${port}`;
@@ -193,7 +176,7 @@
193176
range.selectNodeContents(element);
194177
selection.removeAllRanges();
195178
selection.addRange(range);
196-
clipboard.writeText(event.target.textContent);
179+
electron.clipboard.writeText(event.target.textContent);
197180

198181
const $promptDiv = $("#box-content-prompt");
199182
const $confirmationDiv = $("#box-content-confirmation");
@@ -221,7 +204,7 @@
221204
const link = $('#rn-help-link');
222205
link.addEventListener('click', event => {
223206
event.preventDefault();
224-
require('electron').shell.openExternal(link.href);
207+
electron.shell.openExternal(link.href);
225208
});
226209

227210
const $localhost = $("#localhost");
@@ -241,17 +224,8 @@
241224
// Initially attach the listeners
242225
attachListeners();
243226

244-
let devtools;
245-
try {
246-
devtools = require("react-devtools-core/standalone").default;
247-
} catch (err) {
248-
alert(
249-
err.toString() +
250-
"\n\nDid you run `yarn` and `yarn run build` in packages/react-devtools-core?"
251-
);
252-
}
253-
window.devtools = devtools;
254-
window.server = devtools
227+
window.devtools = getDevTools();
228+
window.server = window.devtools
255229
.setContentDOMNode(document.getElementById("container"))
256230
.setDisconnectedCallback(attachListeners)
257231
.setStatusListener(function(status) {

packages/react-devtools/app.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ app.on('ready', function () {
2727
frame: false,
2828
//titleBarStyle: 'customButtonsOnHover',
2929
webPreferences: {
30-
nodeIntegration: true,
31-
nodeIntegrationInWorker: true,
30+
contextIsolation: true, // protect against prototype pollution
31+
enableRemoteModule: false, // turn off remote
32+
sandbox: false, // allow preload script to access file system
33+
preload: join(__dirname, 'preload.js'), // use a preload script to expose node globals
3234
},
3335
});
3436

packages/react-devtools/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
},
2424
"dependencies": {
2525
"cross-spawn": "^5.0.1",
26-
"electron": "^11.1.0",
26+
"electron": "^23.1.2",
2727
"ip": "^1.1.4",
2828
"minimist": "^1.2.3",
2929
"react-devtools-core": "4.27.2",

packages/react-devtools/preload.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const {clipboard, shell, contextBridge} = require('electron');
2+
const fs = require('fs');
3+
const {address} = require('ip');
4+
5+
// Expose protected methods so that render process does not need unsafe node integration
6+
contextBridge.exposeInMainWorld('api', {
7+
electron: {clipboard, shell},
8+
ip: {address},
9+
getDevTools() {
10+
let devtools;
11+
try {
12+
devtools = require('react-devtools-core/standalone').default;
13+
} catch (err) {
14+
alert(
15+
err.toString() +
16+
'\n\nDid you run `yarn` and `yarn run build` in packages/react-devtools-core?',
17+
);
18+
}
19+
return devtools;
20+
},
21+
readEnv() {
22+
let options;
23+
let useHttps = false;
24+
try {
25+
if (process.env.KEY && process.env.CERT) {
26+
options = {
27+
key: fs.readFileSync(process.env.KEY),
28+
cert: fs.readFileSync(process.env.CERT),
29+
};
30+
useHttps = true;
31+
}
32+
} catch (err) {
33+
console.error('Failed to process SSL options - ', err);
34+
options = undefined;
35+
}
36+
const host = process.env.HOST || 'localhost';
37+
const protocol = useHttps ? 'https' : 'http';
38+
const port = +process.env.PORT || 8097;
39+
return {options, useHttps, host, protocol, port};
40+
},
41+
});

0 commit comments

Comments
 (0)