mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
JavaScript: Add query for Node.js integration in Electron framework
This commit is contained in:
56
javascript/ql/src/Electron/EnablingNodeIntegration.qhelp
Normal file
56
javascript/ql/src/Electron/EnablingNodeIntegration.qhelp
Normal file
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Enabling Node.js integration in web content renderers (BrowserWindow, BrowserView and webview) could result in
|
||||
remote native code execution attacks when rendering malicious JavaScript code from untrusted remote web site or
|
||||
code that is injected via a cross site scripting vulnerability into the web content under processing. Please note that
|
||||
the nodeIntegration property is enabled by default in Electron and needs to be set to 'false' explicitly.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Node.js integration should be disabled when loading remote web sites. If not possible, always set nodeIntegration property
|
||||
to 'false' before loading remote web sites and only enable it for whitelisted sites.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows insecure use of BrowserWindow with regards to <code>nodeIntegration</code>
|
||||
property:
|
||||
</p>
|
||||
<sample src="examples/DefaultNodeIntegration.js"/>
|
||||
|
||||
<p>
|
||||
This is problematic, because default value of nodeIntegration is 'true'.
|
||||
</p>
|
||||
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows insecure and secure uses of <webview> tag:
|
||||
</p>
|
||||
<sample src="examples/WebViewNodeIntegration.html"/>
|
||||
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows insecure and secure uses of BrowserWindow and BrowserView when
|
||||
loading untrusted web sites:
|
||||
</p>
|
||||
<sample src="examples/EnablingNodeIntegration.js"/>
|
||||
|
||||
</example>
|
||||
|
||||
|
||||
<references>
|
||||
<li>Electron Documentation: <a href="https://electronjs.org/docs/tutorial/security#2-disable-nodejs-integration-for-remote-content">Security, Native Capabilities, and Your Responsibility</a></li>
|
||||
</references>
|
||||
</qhelp>
|
||||
28
javascript/ql/src/Electron/EnablingNodeIntegration.ql
Normal file
28
javascript/ql/src/Electron/EnablingNodeIntegration.ql
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @name Enabling nodeIntegration and nodeIntegrationInWorker in webPreferences
|
||||
* @description Enabling nodeIntegration and nodeIntegrationInWorker could expose your app to remote code execution.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision very-high
|
||||
* @tags security
|
||||
* frameworks/electron
|
||||
* @id js/enabling-electron-renderer-node-integration
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
string checkWebOptions(DataFlow::PropWrite prop, Electron::WebPreferences pref) {
|
||||
(prop = pref.getAPropertyWrite("nodeIntegration") and
|
||||
prop.getRhs().mayHaveBooleanValue(true) and
|
||||
result = "nodeIntegration property may have been enabled on this object that could result in RCE")
|
||||
or
|
||||
(prop = pref.getAPropertyWrite("nodeIntegrationInWorker") and
|
||||
prop.getRhs().mayHaveBooleanValue(true) and
|
||||
result = "nodeIntegrationInWorker property may have been enabled on this object that could result in RCE")
|
||||
or
|
||||
(not exists(pref.asExpr().(ObjectExpr).getPropertyByName("nodeIntegration")) and
|
||||
result = "nodeIntegration is enabled by default in WebPreferences object that could result in RCE")
|
||||
}
|
||||
|
||||
from DataFlow::PropWrite property, Electron::WebPreferences preferences
|
||||
select preferences,checkWebOptions(property, preferences)
|
||||
@@ -0,0 +1,2 @@
|
||||
const win = new BrowserWindow();
|
||||
win.loadURL("https://untrusted-site.com");
|
||||
@@ -0,0 +1,26 @@
|
||||
//BAD
|
||||
win_1 = new BrowserWindow({width: 800, height: 600, webPreferences: {nodeIntegration: true}});
|
||||
win_1.loadURL("https://untrusted-site.com");
|
||||
|
||||
//GOOD
|
||||
win_2 = new BrowserWindow({width: 800, height: 600, webPreferences: {nodeIntegration: false}});
|
||||
win_2.loadURL("https://untrusted-site.com");
|
||||
|
||||
//BAD
|
||||
win_3 = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegrationInWorker: true
|
||||
}
|
||||
});
|
||||
|
||||
//BAD BrowserView
|
||||
win_4 = new BrowserWindow({width: 800, height: 600, webPreferences: {nodeIntegration: false}})
|
||||
view = new BrowserView({
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
});
|
||||
win.setBrowserView(view);
|
||||
view.setBounds({ x: 0, y: 0, width: 300, height: 300 });
|
||||
view.webContents.loadURL('https://untrusted-site.com');
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset = "UTF-8">
|
||||
<title>WebView Examples</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- BAD -->
|
||||
<webview src="https://untrusted-site.com/" nodeintegration></webview>
|
||||
|
||||
<!-- GOOD -->
|
||||
<webview src="https://untrusted-site.com/"></webview>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user