VYPR
High severityCISA KEVNVD Advisory· Published Feb 16, 2021· Updated Oct 21, 2025

Command Injection Vulnerability

CVE-2021-21315

Description

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.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
systeminformationnpm
< 5.3.15.3.1

Affected products

1

Patches

1
07daa05fb06f

docker, processLoad fixed potential security issue

https://github.com/sebhildebrandt/systeminformationSebastian HildebrandtFeb 14, 2021via ghsa
4 files changed · +77 28
  • lib/docker.js+48 16 modified
    @@ -109,6 +109,9 @@ function dockerContainers(all, callback) {
         callback = all;
         all = false;
       }
    +  if (typeof all !== 'boolean' && all !== undefined) {
    +    all = false;
    +  }
     
       all = all || false;
       let result = [];
    @@ -185,16 +188,20 @@ function dockerContainers(all, callback) {
     // container inspect (for one container)
     
     function dockerContainerInspect(containerID, payload) {
    -  containerID = containerID || '';
       return new Promise((resolve) => {
         process.nextTick(() => {
    -      if (containerID) {
    +      containerID = containerID || '';
    +      if (typeof containerID !== 'string') {
    +        resolve();
    +      }
    +      const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
    +      if (containerIdSanitized) {
     
             if (!_docker_socket) {
               _docker_socket = new DockerSocket();
             }
     
    -        _docker_socket.getInspect(containerID.trim(), data => {
    +        _docker_socket.getInspect(containerIdSanitized.trim(), data => {
               try {
                 resolve({
                   id: payload.Id,
    @@ -325,19 +332,39 @@ function docker_calcBlockIO(blkio_stats) {
     function dockerContainerStats(containerIDs, callback) {
     
       let containerArray = [];
    -  // 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('|');
    -  }
    -
       return new Promise((resolve) => {
         process.nextTick(() => {
     
    +      // 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('|');
    +      }
    +
           const result = [];
     
           const workload = [];
    @@ -444,17 +471,22 @@ exports.dockerContainerStats = dockerContainerStats;
     // container processes (for one container)
     
     function dockerContainerProcesses(containerID, callback) {
    -  containerID = containerID || '';
       let result = [];
       return new Promise((resolve) => {
         process.nextTick(() => {
    -      if (containerID) {
    +      containerID = containerID || '';
    +      if (typeof containerID !== 'string') {
    +        resolve(result);
    +      }
    +      const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
    +
    +      if (containerIdSanitized) {
     
             if (!_docker_socket) {
               _docker_socket = new DockerSocket();
             }
     
    -        _docker_socket.getProcesses(containerID, data => {
    +        _docker_socket.getProcesses(containerIdSanitized, data => {
               /**
                * @namespace
                * @property {Array}  Titles
    
  • lib/internet.js+2 2 modified
    @@ -40,7 +40,7 @@ function inetChecksite(url, callback) {
             status: 404,
             ms: null
           };
    -      if (typeof url !== "string") {
    +      if (typeof url !== 'string') {
             if (callback) { callback(result); }
             return resolve(result);
           }
    @@ -131,7 +131,7 @@ function inetLatency(host, callback) {
     
       return new Promise((resolve) => {
         process.nextTick(() => {
    -      if (typeof host !== "string") {
    +      if (typeof host !== 'string') {
             if (callback) { callback(null); }
             return resolve(null);
           }
    
  • lib/network.js+19 9 modified
    @@ -973,19 +973,29 @@ function calcNetworkSpeed(iface, rx_bytes, tx_bytes, operstate, rx_dropped, rx_e
     function networkStats(ifaces, callback) {
     
       let ifacesArray = [];
    -  // 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('|');
    -  }
     
       return new Promise((resolve) => {
         process.nextTick(() => {
     
    +      // 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('|');
    +      }
    +
           const result = [];
     
           const workload = [];
    
  • lib/processes.js+8 1 modified
    @@ -99,7 +99,7 @@ function services(srv, callback) {
     
       return new Promise((resolve) => {
         process.nextTick(() => {
    -      if (typeof srv !== "string") {
    +      if (typeof srv !== 'string') {
             if (callback) { callback([]); }
             return resolve([]);
           }
    @@ -892,6 +892,13 @@ function processLoad(proc, callback) {
       return new Promise((resolve) => {
         process.nextTick(() => {
     
    +      proc = proc || '';
    +
    +      if (typeof proc !== 'string') {
    +        if (callback) { callback([]); }
    +        return resolve([]);
    +      }
    +
           let processesString = '';
           processesString.__proto__.toLowerCase = util.stringToLower;
           processesString.__proto__.replace = util.stringReplace;
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

10

News mentions

0

No linked articles in our index yet.