CVE-2021-21315 (JavaScript, published 2021-02-16T17:15Z)
Description: value: The System Information Library for Node.JS (npm package "systeminformation") is an open source collection of functions to retrieve detailed hardware, system and OS information. In systeminformation before version 5.3.1 there is a command injection vulnerability. Problem was fixed in version 5.3.1. As a workaround instead of upgrading, be sure to check or sanitize service parameters that are passed to si.inetLatency(), si.inetChecksite(), si.services(), si.processLoad() ... do only allow strings, reject any arrays. String sanitation works as expected.
Severity: MEDIUM (CVSS v3 base score: 7.8)
Weakness: CWE-78 \u2014 Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
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.
Repository: https://github.com/sebhildebrandt/systeminformation
Files changed:
lib/docker.js
lib/internet.js
lib/network.js
lib/processes.js
Commit message: docker, processLoad fixed potential security issue


Vulnerable code:
  containerID = containerID || '';
      if (containerID) {
        _docker_socket.getInspect(containerID.trim(), data => {
  // fallback - if only callback is given
  if (util.isFunction(containerIDs) && !callback) {
    callback = containerIDs;
    containerArray = ['*'];
  } else {
    containerIDs = containerIDs || '*';
    containerIDs = containerIDs.trim().toLowerCase().replace(/,+/g, '|');
    containerArray = containerIDs.split('|');
  }

  containerID = containerID || '';
      if (containerID) {
        _docker_socket.getProcesses(containerID, data => {
      if (typeof url !== "string") {
      if (typeof host !== "string") {
  // fallback - if only callback is given
  if (util.isFunction(ifaces) && !callback) {
    callback = ifaces;
    ifacesArray = [getDefaultNetworkInterface()];
  } else {
    ifaces = ifaces || getDefaultNetworkInterface();
    ifaces = ifaces.trim().toLowerCase().replace(/,+/g, '|');
    ifacesArray = ifaces.split('|');
  }
      if (typeof srv !== "string") {

Fixed code:
  if (typeof all !== 'boolean' && all !== undefined) {
    all = false;
  }
      containerID = containerID || '';
      if (typeof containerID !== 'string') {
        resolve();
      }
      const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
      if (containerIdSanitized) {
        _docker_socket.getInspect(containerIdSanitized.trim(), data => {
      // fallback - if only callback is given
      if (util.isFunction(containerIDs) && !callback) {
        callback = containerIDs;
        containerArray = ['*'];
      } else {
        containerIDs = containerIDs || '*';
        if (typeof containerIDs !== 'string') {
          if (callback) { callback([]); }
          return resolve([]);
        }
        let containerIDsSanitized = '';
        containerIDsSanitized.__proto__.toLowerCase = util.stringToLower;
        containerIDsSanitized.__proto__.replace = util.stringReplace;
        containerIDsSanitized.__proto__.trim = util.stringTrim;

        const s = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerIDs, true)).trim();
        for (let i = 0; i <= 2000; i++) {
          if (!(s[i] === undefined)) {
            s[i].__proto__.toLowerCase = util.stringToLower;
            const sl = s[i].toLowerCase();
            if (sl && sl[0] && !sl[1]) {
              containerIDsSanitized = containerIDsSanitized + sl[0];
            }
          }
        }

        containerIDsSanitized = containerIDsSanitized.trim().toLowerCase().replace(/,+/g, '|');
        containerArray = containerIDs.split('|');
      }

      containerID = containerID || '';
      if (typeof containerID !== 'string') {
        resolve(result);
      }
      const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();

      if (containerIdSanitized) {
        _docker_socket.getProcesses(containerIdSanitized, data => {
      if (typeof url !== 'string') {
      if (typeof host !== 'string') {
      // fallback - if only callback is given
      if (util.isFunction(ifaces) && !callback) {
        callback = ifaces;
        ifacesArray = [getDefaultNetworkInterface()];
      } else {
        if (typeof ifaces !== 'string' && ifaces !== undefined) {
          if (callback) { callback([]); }
          return resolve([]);
        }
        ifaces = ifaces || getDefaultNetworkInterface();

        ifaces.__proto__.toLowerCase = util.stringToLower;
        ifaces.__proto__.replace = util.stringReplace;
        ifaces.__proto__.trim = util.stringTrim;

        ifaces = ifaces.trim().toLowerCase().replace(/,+/g, '|');
        ifacesArray = ifaces.split('|');
      }

      if (typeof srv !== 'string') {
      proc = proc || '';

      if (typeof proc !== 'string') {
        if (callback) { callback([]); }
        return resolve([]);
      }