Zennoxa Shield
Rules / JavaScript / TypeScript
SHIELD-JS-009

Command injection via exec/spawn

criticalJavaScript / TypeScriptCWE-78CVSS 9.8

What it detects

Executing shell commands with unsanitized user input allows command injection.

How to fix

Avoid passing user input to shell commands. Use execFile with an argument array instead of exec.

Vulnerable — Shield flags thisping.js
const { exec } = require("child_process");
const express = require("express");
const app = express();

app.get("/ping", (req, res) => {
  // ?host=8.8.8.8;cat /etc/passwd runs arbitrary commands
  exec("ping -c 1 " + req.query.host, (err, stdout) => {
    res.type("text").send(stdout);
  });
});
Fixed — scans cleanping.js
const { execFile } = require("child_process");
const express = require("express");
const app = express();

// Ping only known monitoring targets; host is never taken from the request
app.get("/ping", (req, res) => {
  let host;
  switch (req.query.target) {
    case "primary": host = "db-primary.internal"; break;
    case "backup": host = "db-backup.internal"; break;
    default: return res.status(400).send("unknown target");
  }
  execFile("ping", ["-c", "1", host], (err, stdout) => {
    res.type("text").send(stdout);
  });
});

Both snippets are verified against the shipped scanner: the vulnerable one triggers SHIELD-JS-009, the fixed one does not.

SHIELD-JS-009: Command injection via exec/spawn — Zennoxa Shield