Skip to content

Commit 6178d6b

Browse files
committed
Fix command injection in WebAuth.js open() — replace exec() with execFile() #6089
1 parent 2a48705 commit 6178d6b

2 files changed

Lines changed: 21 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Drop auto source map file detection in Common.prepareAppConf
2020
- Fix HttpInterface env stripping never executing (WEB_STRIP_ENV_VARS) #6089
2121
- Fix prototype pollution in Configuration.set/unset via __proto__ key traversal #6089
22+
- Fix command injection in WebAuth.js open() — replace exec() with execFile() #6089
2223

2324
## 6.0.14
2425

lib/API/pm2-plus/auth-strategies/WebAuth.js

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const cst = require('../../../../constants.js');
66
const AuthStrategy = require('@pm2/js-api/src/auth_strategies/strategy')
77
const http = require('http')
88
const fs = require('fs')
9-
const exec = require('child_process').exec
9+
const { execFile } = require('child_process')
1010
const tryEach = require('async/tryEach');
1111

1212
module.exports = class WebStrategy extends AuthStrategy {
@@ -153,34 +153,43 @@ module.exports = class WebStrategy extends AuthStrategy {
153153
}
154154

155155
open (target, appName, callback) {
156-
let opener
157-
const escape = function (s) {
158-
return s.replace(/"/g, '\\"')
159-
}
160-
161156
if (typeof (appName) === 'function') {
162157
callback = appName
163158
appName = null
164159
}
165160

161+
let cmd
162+
let args = []
163+
166164
switch (process.platform) {
167165
case 'darwin': {
168-
opener = appName ? `open -a "${escape(appName)}"` : `open`
166+
cmd = 'open'
167+
if (appName) args.push('-a', appName)
168+
args.push(target)
169169
break
170170
}
171171
case 'win32': {
172-
opener = appName ? `start "" ${escape(appName)}"` : `start ""`
172+
cmd = 'cmd'
173+
args = ['/c', 'start', '""']
174+
if (appName) args.push(appName)
175+
args.push(target)
173176
break
174177
}
175178
default: {
176-
opener = appName ? escape(appName) : `xdg-open`
179+
cmd = appName || 'xdg-open'
180+
args.push(target)
177181
break
178182
}
179183
}
180184

181185
if (process.env.SUDO_USER) {
182-
opener = 'sudo -u ' + process.env.SUDO_USER + ' ' + opener
186+
if (!/^[a-zA-Z0-9._-]+$/.test(process.env.SUDO_USER)) {
187+
return callback && callback(new Error('Invalid SUDO_USER'))
188+
}
189+
args = ['-u', process.env.SUDO_USER, cmd].concat(args)
190+
cmd = 'sudo'
183191
}
184-
return exec(`${opener} "${escape(target)}"`, callback)
192+
193+
return execFile(cmd, args, callback)
185194
}
186195
}

0 commit comments

Comments
 (0)