CVE-2021-21388: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') (CWE-78)
value: systeminformation is an open source system and OS information library for node.js. A command injection vulnerability has been discovered in versions of systeminformation prior to 5.6.4. The issue has been fixed with a parameter check on user input. Please upgrade to version >= 5.6.4. If you cannot upgrade, be sure to check or sanitize service parameters that are passed to si.inetLatency(), si.inetChecksite(), si.services(), si.processLoad() and other commands. Only allow strings, reject any arrays. String sanitation works as expected.
CWE description: The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
CVSS v3 base score: 9.8
Published: 2021-04-29T18:15Z
Repository: https://github.com/sebhildebrandt/systeminformation
Language: HTML
Files changed: CHANGELOG.md, docs/history.html, docs/index.html, docs/security.html, docs/v4/history.html, docs/v4/index.html, docs/v4/security.html, lib/internet.js, lib/network.js, lib/processes.js, lib/util.js
Commit date: 2021-03-15 11:21:32 +0100
Commit message: sanitizeShellString() and other security improvements

Diff: diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40e1f1ce..94be3e97 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -75,11 +75,12 @@ For major (breaking) changes - **version 4, 3 and 2** - see end of page.
 
 ## Version history
 
 | Version        | Date           | Comment  |
 | -------------- | -------------- | -------- |
-| 5.6.3          | 2021-03-10     | `sanitizeShellString()` improvement |
+| 5.6.4          | 2021-03-15     | `sanitizeShellString()` and other security improvements |
+| 5.6.3          | 2021-03-14     | `sanitizeShellString()` improvement |
 | 5.6.2          | 2021-03-10     | `networkInterfaces()` `cpu()` improvement (win) |
 | 5.6.1          | 2021-03-03     | `get()` fixed issue boolean parameters |
 | 5.6.0          | 2021-03-03     | `cpuTemperature()` added socket and chipset temp (linux) |
 | 5.5.0          | 2021-02-25     | `dockerVolumes()` added |
 | 5.4.0          | 2021-02-24     | `dockerImages()` added |
diff --git a/docs/history.html b/docs/history.html
index f91d5343..3e66d56c 100644
--- a/docs/history.html
+++ b/docs/history.html
@@ -54,10 +54,15 @@
                     <th scope="col">Date</th>
                     <th scope="col">Comment</th>
                   </tr>
                 </thead>
                 <tbody>
+                  <tr>
+                    <th scope="row">5.6.4</th>
+                    <td>2021-03-15</td>
+                    <td><span class="code">sanitizeShellString()</span> and other security improvements</td>
+                  </tr>
                   <tr>
                     <th scope="row">5.6.3</th>
                     <td>2021-03-14</td>
                     <td><span class="code">sanitizeShellString()</span> improvements</td>
                   </tr>
diff --git a/docs/index.html b/docs/index.html
index dfaecafa..62622269 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -164,15 +164,15 @@
 </head>
 
 <body>
   <header class="bg-image-full">
     <div class="top-container">
-      <a href="security.html" class="recommendation">Security advisory:<br>Update to v5.6.3</a>
+      <a href="security.html" class="recommendation">Security advisory:<br>Update to v5.6.4</a>
       <img class="logo" src="assets/logo.png">
       <div class="title">systeminformation</div>
       <div class="subtitle"><span id="typed"></span>&nbsp;</div>
-      <div class="version">New Version: <span id="version">5.6.3</span></div>
+      <div class="version">New Version: <span id="version">5.6.4</span></div>
       <button class="btn btn-light" onclick="location.href='https://github.com/sebhildebrandt/systeminformation'">View on Github <i class=" fab fa-github"></i></button>
     </div>
     <div class="down">
       <button class="btn btn-primary mb-2" onclick="location.href='https://www.buymeacoffee.com/systeminfo'">Buy me a coffee&nbsp;&nbsp;<i class="far fa-mug-hot"></i></button>
       <br>Read Documentation<br>
diff --git a/docs/security.html b/docs/security.html
index aff46fb1..3eeb8a86 100644
--- a/docs/security.html
+++ b/docs/security.html
@@ -43,20 +43,20 @@
           <div class="col-12 sectionheader">
             <div class="title">Security Advisories</div>
             <div class="text">
               <h2>Command Injection Vulnerability</h2>
               <p><span class="bold">Affected versions:</span>
-                &lt; 5.6.3 and &lt; 4.34.16<br>
-                <span class="bold">Date:</span> 2021-03-14<br>
+                &lt; 5.6.4 and &lt; 4.34.17<br>
+                <span class="bold">Date:</span> 2021-03-15<br>
                 <span class="bold">CVE indentifier</span> -
               </p>
 
               <h4>Impact</h4>
               <p>We had an issue that there was a possibility to perform a potential command injection possibility by passing a manipulated string prototype as a parameter to the following functions. Affected commands: <span class="code">inetLatency()</span>, <span class="code">inetChecksite()</span>, <span class="code">services()</span>, <span class="code">processLoad()</span>.</p>
 
               <h4>Patch</h4>
-              <p>Problem was fixed with additional parameter checking. Please upgrade to version >= 5.6.3 (or >= 4.34.16 if you are using version 4).</p>
+              <p>Problem was fixed with additional parameter checking. Please upgrade to version >= 5.6.4 (or >= 4.34.17 if you are using version 4).</p>
 
               <h4>Workarround</h4>
               <p>If you cannot upgrade, be sure to check or sanitize parameter strings that are passed to <span class="code">inetLatency()</span>, <span class="code">inetChecksite()</span>, <span class="code">services()</span>, <span class="code">processLoad()</span> (string only)</p>
               <hr>
               <br>
diff --git a/docs/v4/history.html b/docs/v4/history.html
index 8efd9315..55aa575e 100644
--- a/docs/v4/history.html
+++ b/docs/v4/history.html
@@ -81,10 +81,15 @@
                     <th scope="col">Date</th>
                     <th scope="col">Comment</th>
                   </tr>
                 </thead>
                 <tbody>
+                  <tr>
+                    <th scope="row">4.34.17</th>
+                    <td>2021-03-14</td>
+                    <td><span class="code">sanitizeShellString()</span> and other security improvements</td>
+                  </tr>
                   <tr>
                     <th scope="row">4.34.16</th>
                     <td>2021-03-14</td>
                     <td><span class="code">sanitizeShellString()</span> improvements</td>
                   </tr>
diff --git a/docs/v4/index.html b/docs/v4/index.html
index b51e9d86..2b085559 100644
--- a/docs/v4/index.html
+++ b/docs/v4/index.html
@@ -163,16 +163,16 @@
 </head>
 
 <body>
   <header class="bg-image-full">
     <div class="container">
-      <a href="security.html" class="recommendation">Security advisory:<br>Update to v4.34.16</a>
+      <a href="security.html" class="recommendation">Security advisory:<br>Update to v4.34.17</a>
       <img class="logo" src="assets/logo.png">
       <div class="title">systeminformation </div>
       <div class="subtitle"><span id="typed"></span>&nbsp;</div>
       <div class="version larger">Version 4 documentation</div>
-      <div class="version">Current Version: <span id="version">4.34.16</span></div>
+      <div class="version">Current Version: <span id="version">4.34.17</span></div>
       <button class="btn btn-light" onclick="location.href='https://github.com/sebhildebrandt/systeminformation'">View on Github <i class=" fab fa-github"></i></button>
     </div>
     <div class="down">
       <button class="btn btn-primary mb-2" onclick="location.href='https://www.buymeacoffee.com/systeminfo'">Buy me a coffee&nbsp;&nbsp;<i class="far fa-mug-hot"></i></button>
       <br>Read Documentation<br>
diff --git a/docs/v4/security.html b/docs/v4/security.html
index f478020d..3907e78f 100644
--- a/docs/v4/security.html
+++ b/docs/v4/security.html
@@ -42,20 +42,20 @@
           <div class="col-12 sectionheader">
             <div class="title">Security Advisories</div>
             <div class="text">
               <h2>Command Injection Vulnerability</h2>
               <p><span class="bold">Affected versions:</span>
-                &lt; 4.34.13<br>
-                <span class="bold">Date:</span> 2021-03-14<br>
+                &lt; 4.34.17<br>
+                <span class="bold">Date:</span> 2021-03-15<br>
                 <span class="bold">CVE indentifier</span> -
               </p>
 
               <h4>Impact</h4>
               <p>We had an issue that there was a possibility to perform a potential command injection possibility by passing a manipulated string prototype as a parameter to the following functions. Affected commands: <span class="code">inetLatency()</span>, <span class="code">inetChecksite()</span>, <span class="code">services()</span>, <span class="code">processLoad()</span>.</p>
 
               <h4>Patch</h4>
-              <p>Problem was fixed with additional parameter checking. Please upgrade to version >= 4.34.13 if you are using version 4.</p>
+              <p>Problem was fixed with additional parameter checking. Please upgrade to version >= 4.34.17 if you are using version 4.</p>
 
               <h4>Workarround</h4>
               <p>If you cannot upgrade, be sure to check or sanitize parameter strings that are passed to <span class="code">inetLatency()</span>, <span class="code">inetChecksite()</span>, <span class="code">services()</span>, <span class="code">processLoad()</span> (string only)</p>
               <hr>
               <br>
diff --git a/lib/internet.js b/lib/internet.js
index 6c4e9af9..9ac1e717 100644
--- a/lib/internet.js
+++ b/lib/internet.js
@@ -11,11 +11,11 @@
 // License:       MIT
 // ==================================================================================
 // 12. Internet
 // ----------------------------------------------------------------------------------
 
-const exec = require('child_process').exec;
+// const exec = require('child_process').exec;
 const execFile = require('child_process').execFile;
 const util = require('./util');
 
 let _platform = process.platform;
 
@@ -44,15 +44,16 @@ function inetChecksite(url, callback) {
         if (callback) { callback(result); }
         return resolve(result);
       }
       let urlSanitized = '';
       const s = util.sanitizeShellString(url, true);
-      for (let i = 0; i <= 2000; i++) {
+      const mathMin = util.mathMin;
+      for (let i = 0; i <= mathMin(s.length, 2000); i++) {
         if (!(s[i] === undefined)) {
           s[i].__proto__.toLowerCase = util.stringToLower;
           const sl = s[i].toLowerCase();
-          if (sl && sl[0] && !sl[1]) {
+          if (sl && sl[0] && !sl[1] && sl[0].length === 1) {
             urlSanitized = urlSanitized + sl[0];
           }
         }
       }
       result.url = urlSanitized;
@@ -63,16 +64,18 @@ function inetChecksite(url, callback) {
             if (callback) { callback(result); }
             return resolve(result);
           }
           let t = Date.now();
           if (_linux || _freebsd || _openbsd || _netbsd || _darwin || _sunos) {
-            let args = ' -I --connect-timeout 5 -m 5 ' + urlSanitized + ' 2>/dev/null | head -n 1 | cut -d " " -f2';
+            let args = ['-I', '--connect-timeout', '5', '-m', '5'];
+            args.push(urlSanitized);
             let cmd = 'curl';
-            exec(cmd + args, function (error, stdout) {
-              let statusCode = parseInt(stdout.toString());
+            util.execSave(cmd, args).then((stdout) => {
+              const lines = stdout.split('\n');
+              let statusCode = lines[0] && lines[0].indexOf(' ') >= 0 ? parseInt(lines[0].split(' ')[1], 10) : 404;
               result.status = statusCode || 404;
-              result.ok = !error && (statusCode === 200 || statusCode === 301 || statusCode === 302 || statusCode === 304);
+              result.ok = (statusCode === 200 || statusCode === 301 || statusCode === 302 || statusCode === 304);
               result.ms = (result.ok ? Date.now() - t : null);
               if (callback) { callback(result); }
               resolve(result);
             });
           }
@@ -140,11 +143,12 @@ function inetLatency(host, callback) {
         if (callback) { callback(null); }
         return resolve(null);
       }
       let hostSanitized = '';
       const s = (util.isPrototypePolluted() ? '8.8.8.8' : util.sanitizeShellString(host, true)).trim();
-      for (let i = 0; i <= 2000; i++) {
+      const mathMin = util.mathMin;
+      for (let i = 0; i <= mathMin(s.length, 2000); i++) {
         if (!(s[i] === undefined)) {
           s[i].__proto__.toLowerCase = util.stringToLower;
           const sl = s[i].toLowerCase();
           if (sl && sl[0] && !sl[1]) {
             hostSanitized = hostSanitized + sl[0];
@@ -169,14 +173,14 @@ function inetLatency(host, callback) {
         }
         if (_darwin) {
           params = '-c2 -t3 ' + hostSanitized;
           filt = 'avg';
         }
-        execFile('ping', params.split(' '), function (error, stdout) {
+        util.execSave('ping', params.split(' ')).then((stdout) => {
           let result = null;
-          if (!error) {
-            const lines = stdout.toString().split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
+          if (stdout) {
+            const lines = stdout.split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
 
             const line = lines.split('=');
             if (line.length > 1) {
               const parts = line[1].split('/');
               if (parts.length > 1) {
@@ -189,14 +193,14 @@ function inetLatency(host, callback) {
         });
       }
       if (_sunos) {
         const params = '-s -a ' + hostSanitized + ' 56 2';
         const filt = 'avg';
-        execFile('ping', params.split(' '), { timeout: 3000 }, function (error, stdout) {
+        util.execSave('ping', params.split(' '), { timeout: 3000 }).then((stdout) => {
           let result = null;
-          if (!error) {
-            const lines = stdout.toString().split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
+          if (stdout) {
+            const lines = stdout.split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
             const line = lines.split('=');
             if (line.length > 1) {
               const parts = line[1].split('/');
               if (parts.length > 1) {
                 result = parseFloat(parts[1].replace(',', '.'));
diff --git a/lib/network.js b/lib/network.js
index 9e1087bb..5398ece2 100644
--- a/lib/network.js
+++ b/lib/network.js
@@ -1059,11 +1059,12 @@ function networkStatsSingle(iface) {
 
   return new Promise((resolve) => {
     process.nextTick(() => {
       let ifaceSanitized = '';
       const s = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(iface);
-      for (let i = 0; i <= 2000; i++) {
+      const mathMin = util.mathMin;
+      for (let i = 0; i <= mathMin(s.length, 2000); i++) {
         if (!(s[i] === undefined)) {
           ifaceSanitized = ifaceSanitized + s[i];
         }
       }
 
diff --git a/lib/processes.js b/lib/processes.js
index 400c01f1..2f234c6c 100644
--- a/lib/processes.js
+++ b/lib/processes.js
@@ -109,11 +109,12 @@ function services(srv, callback) {
         srvString.__proto__.toLowerCase = util.stringToLower;
         srvString.__proto__.replace = util.stringReplace;
         srvString.__proto__.trim = util.stringTrim;
 
         const s = util.sanitizeShellString(srv);
-        for (let i = 0; i <= 2000; i++) {
+        const mathMin = util.mathMin;
+        for (let i = 0; i <= mathMin(s.length, 2000); i++) {
           if (!(s[i] === undefined)) {
             srvString = srvString + s[i];
           }
         }
 
@@ -162,19 +163,19 @@ function services(srv, callback) {
                 srvString = '';
                 srvs = [];
               }
             }
           }
-          if ((_darwin) && srvString === '*') { // service enumeration mnot yet suported on mac OS
+          if ((_darwin) && srvString === '*') { // service enumeration not yet suported on mac OS
             if (callback) { callback(result); }
             resolve(result);
           }
-          let comm = (_darwin) ? 'ps -caxo pcpu,pmem,pid,command' : 'ps -axo pcpu,pmem,pid,command';
+          let args = (_darwin) ? ['-caxo', 'pcpu,pmem,pid,command'] : ['-axo', 'pcpu,pmem,pid,command'];
           if (srvString !== '' && srvs.length > 0) {
-            exec(comm + ' | grep -v grep | grep -iE "' + srvString + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) {   // lgtm [js/shell-command-constructed-from-input]
-              if (!error) {
-                let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
+            util.execSave('ps', args).then((stdout) => {
+              if (stdout) {
+                let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
                 srvs.forEach(function (srv) {
                   let ps;
                   if (_darwin) {
                     ps = lines.filter(function (e) {
                       return (e.toLowerCase().indexOf(srv) !== -1);
@@ -265,13 +266,14 @@ function services(srv, callback) {
                 } else {
                   if (callback) { callback(result); }
                   resolve(result);
                 }
               } else {
-                exec('ps -o comm | grep -v grep | egrep "' + srvString + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) {   // lgtm [js/shell-command-constructed-from-input]
-                  if (!error) {
-                    let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
+                args = ['-o', 'comm'];
+                util.execSave('ps', args).then((stdout) => {
+                  if (stdout) {
+                    let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
                     srvs.forEach(function (srv) {
                       let ps = lines.filter(function (e) {
                         return e.indexOf(srv) !== -1;
                       });
                       result.push({
@@ -907,11 +909,12 @@ function processLoad(proc, callback) {
       processesString.__proto__.toLowerCase = util.stringToLower;
       processesString.__proto__.replace = util.stringReplace;
       processesString.__proto__.trim = util.stringTrim;
 
       const s = util.sanitizeShellString(proc);
-      for (let i = 0; i <= 2000; i++) {
+      const mathMin = util.mathMin;
+      for (let i = 0; i <= mathMin(s.length, 2000); i++) {
         if (!(s[i] === undefined)) {
           processesString = processesString + s[i];
         }
       }
 
diff --git a/lib/util.js b/lib/util.js
index 04e5a89e..d5c689fe 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -56,10 +56,11 @@ const stringReplace = new String().replace;
 const stringToLower = new String().toLowerCase;
 const stringToString = new String().toString;
 const stringSubstr = new String().substr;
 const stringTrim = new String().trim;
 const stringStartWith = new String().startsWith;
+const mathMin = Math.min;
 
 function isFunction(functionToCheck) {
   let getType = {};
   return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
 }
@@ -387,10 +388,46 @@ function powerShell(cmd) {
       }
     });
   });
 }
 
+function execSave(cmd, args, options) {
+  let result = '';
+  options = options || {};
+
+  return new Promise((resolve) => {
+    process.nextTick(() => {
+      try {
+        const child = spawn(cmd, args, options);
+
+        if (child && !child.pid) {
+          child.on('error', function () {
+            resolve(result);
+          });
+        }
+        if (child && child.pid) {
+          child.stdout.on('data', function (data) {
+            result += data.toString();
+          });
+          child.on('close', function () {
+            child.kill();
+            resolve(result);
+          });
+          child.on('error', function () {
+            child.kill();
+            resolve(result);
+          });
+        } else {
+          resolve(result);
+        }
+      } catch (e) {
+        resolve(result);
+      }
+    });
+  });
+}
+
 function getCodepage() {
   if (_windows) {
     if (!codepage) {
       try {
         const stdout = execSync('chcp', execOptsWin);
@@ -504,11 +541,11 @@ function countLines(lines, startingWith) {
 }
 
 function sanitizeShellString(str, strict = false) {
   const s = str || '';
   let result = '';
-  for (let i = 0; i <= 2000; i++) {
+  for (let i = 0; i <= mathMin(s.length, 2000); i++) {
     if (!(s[i] === undefined ||
       s[i] === '>' ||
       s[i] === '<' ||
       s[i] === '*' ||
       s[i] === '?' ||
@@ -923,10 +960,11 @@ exports.findObjectByKey = findObjectByKey;
 exports.getWmic = getWmic;
 exports.wmic = wmic;
 exports.darwinXcodeExists = darwinXcodeExists;
 exports.getVboxmanage = getVboxmanage;
 exports.powerShell = powerShell;
+exports.execSave = execSave;
 exports.nanoSeconds = nanoSeconds;
 exports.countUniqueLines = countUniqueLines;
 exports.countLines = countLines;
 exports.noop = noop;
 exports.isRaspberry = isRaspberry;
@@ -941,7 +979,8 @@ exports.stringReplace = stringReplace;
 exports.stringToLower = stringToLower;
 exports.stringToString = stringToString;
 exports.stringSubstr = stringSubstr;
 exports.stringTrim = stringTrim;
 exports.stringStartWith = stringStartWith;
+exports.mathMin = mathMin;
 exports.WINDIR = WINDIR;
 exports.getFilesInPath = getFilesInPath;

Vulnerable code: | 5.6.3          | 2021-03-10     | `sanitizeShellString()` improvement |
      <a href="security.html" class="recommendation">Security advisory:<br>Update to v5.6.3</a>
      <div class="version">New Version: <span id="version">5.6.3</span></div>
                &lt; 5.6.3 and &lt; 4.34.16<br>
                <span class="bold">Date:</span> 2021-03-14<br>
              <p>Problem was fixed with additional parameter checking. Please upgrade to version >= 5.6.3 (or >= 4.34.16 if you are using version 4).</p>
      <a href="security.html" class="recommendation">Security advisory:<br>Update to v4.34.16</a>
      <div class="version">Current Version: <span id="version">4.34.16</span></div>
                &lt; 4.34.13<br>
                <span class="bold">Date:</span> 2021-03-14<br>
              <p>Problem was fixed with additional parameter checking. Please upgrade to version >= 4.34.13 if you are using version 4.</p>
const exec = require('child_process').exec;
      for (let i = 0; i <= 2000; i++) {
          if (sl && sl[0] && !sl[1]) {
            let args = ' -I --connect-timeout 5 -m 5 ' + urlSanitized + ' 2>/dev/null | head -n 1 | cut -d " " -f2';
            exec(cmd + args, function (error, stdout) {
              let statusCode = parseInt(stdout.toString());
              result.ok = !error && (statusCode === 200 || statusCode === 301 || statusCode === 302 || statusCode === 304);
      for (let i = 0; i <= 2000; i++) {
        execFile('ping', params.split(' '), function (error, stdout) {
          if (!error) {
            const lines = stdout.toString().split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
        execFile('ping', params.split(' '), { timeout: 3000 }, function (error, stdout) {
          if (!error) {
            const lines = stdout.toString().split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
      for (let i = 0; i <= 2000; i++) {
        for (let i = 0; i <= 2000; i++) {
          if ((_darwin) && srvString === '*') { // service enumeration mnot yet suported on mac OS
          let comm = (_darwin) ? 'ps -caxo pcpu,pmem,pid,command' : 'ps -axo pcpu,pmem,pid,command';
            exec(comm + ' | grep -v grep | grep -iE "' + srvString + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) {   // lgtm [js/shell-command-constructed-from-input]
              if (!error) {
                let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
                exec('ps -o comm | grep -v grep | egrep "' + srvString + '"', { maxBuffer: 1024 * 20000 }, function (error, stdout) {   // lgtm [js/shell-command-constructed-from-input]
                  if (!error) {
                    let lines = stdout.toString().replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
      for (let i = 0; i <= 2000; i++) {
  for (let i = 0; i <= 2000; i++) {
Fixed code: | 5.6.4          | 2021-03-15     | `sanitizeShellString()` and other security improvements |
| 5.6.3          | 2021-03-14     | `sanitizeShellString()` improvement |
                  <tr>
                    <th scope="row">5.6.4</th>
                    <td>2021-03-15</td>
                    <td><span class="code">sanitizeShellString()</span> and other security improvements</td>
                  </tr>
      <a href="security.html" class="recommendation">Security advisory:<br>Update to v5.6.4</a>
      <div class="version">New Version: <span id="version">5.6.4</span></div>
                &lt; 5.6.4 and &lt; 4.34.17<br>
                <span class="bold">Date:</span> 2021-03-15<br>
              <p>Problem was fixed with additional parameter checking. Please upgrade to version >= 5.6.4 (or >= 4.34.17 if you are using version 4).</p>
                  <tr>
                    <th scope="row">4.34.17</th>
                    <td>2021-03-14</td>
                    <td><span class="code">sanitizeShellString()</span> and other security improvements</td>
                  </tr>
      <a href="security.html" class="recommendation">Security advisory:<br>Update to v4.34.17</a>
      <div class="version">Current Version: <span id="version">4.34.17</span></div>
                &lt; 4.34.17<br>
                <span class="bold">Date:</span> 2021-03-15<br>
              <p>Problem was fixed with additional parameter checking. Please upgrade to version >= 4.34.17 if you are using version 4.</p>
// const exec = require('child_process').exec;
      const mathMin = util.mathMin;
      for (let i = 0; i <= mathMin(s.length, 2000); i++) {
          if (sl && sl[0] && !sl[1] && sl[0].length === 1) {
            let args = ['-I', '--connect-timeout', '5', '-m', '5'];
            args.push(urlSanitized);
            util.execSave(cmd, args).then((stdout) => {
              const lines = stdout.split('\n');
              let statusCode = lines[0] && lines[0].indexOf(' ') >= 0 ? parseInt(lines[0].split(' ')[1], 10) : 404;
              result.ok = (statusCode === 200 || statusCode === 301 || statusCode === 302 || statusCode === 304);
      const mathMin = util.mathMin;
      for (let i = 0; i <= mathMin(s.length, 2000); i++) {
        util.execSave('ping', params.split(' ')).then((stdout) => {
          if (stdout) {
            const lines = stdout.split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
        util.execSave('ping', params.split(' '), { timeout: 3000 }).then((stdout) => {
          if (stdout) {
            const lines = stdout.split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
      const mathMin = util.mathMin;
      for (let i = 0; i <= mathMin(s.length, 2000); i++) {
        const mathMin = util.mathMin;
        for (let i = 0; i <= mathMin(s.length, 2000); i++) {
          if ((_darwin) && srvString === '*') { // service enumeration not yet suported on mac OS
          let args = (_darwin) ? ['-caxo', 'pcpu,pmem,pid,command'] : ['-axo', 'pcpu,pmem,pid,command'];
            util.execSave('ps', args).then((stdout) => {
              if (stdout) {
                let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
                args = ['-o', 'comm'];
                util.execSave('ps', args).then((stdout) => {
                  if (stdout) {
                    let lines = stdout.replace(/ +/g, ' ').replace(/,+/g, '.').split('\n');
      const mathMin = util.mathMin;
      for (let i = 0; i <= mathMin(s.length, 2000); i++) {
const mathMin = Math.min;
function execSave(cmd, args, options) {
  let result = '';
  options = options || {};

  return new Promise((resolve) => {
    process.nextTick(() => {
      try {
        const child = spawn(cmd, args, options);

        if (child && !child.pid) {
          child.on('error', function () {
            resolve(result);
          });
        }
        if (child && child.pid) {
          child.stdout.on('data', function (data) {
            result += data.toString();
          });
          child.on('close', function () {
            child.kill();
            resolve(result);
          });
          child.on('error', function () {
            child.kill();
            resolve(result);
          });
        } else {
          resolve(result);
        }
      } catch (e) {
        resolve(result);
      }
    });
  });
}

  for (let i = 0; i <= mathMin(s.length, 2000); i++) {
exports.execSave = execSave;
exports.mathMin = mathMin;