CVE-2022-25171: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') (CWE-78)
value: The package p4 before 0.0.7 are vulnerable to Command Injection via the run() function due to improper input sanitization
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: 2022-12-20T05:15Z
Repository: https://github.com/natelong/p4
Language: JSON
Files changed: p4.js, package.json
Commit date: 2022-12-12 09:30:15 -0800
Commit message: address security vulnerability

Diff: diff --git a/p4.js b/p4.js
index e154a4b..a4d96d4 100644
--- a/p4.js
+++ b/p4.js
@@ -1,21 +1,37 @@
 /*jshint node:true*/
 "use strict";
 
-var exec = require("child_process").exec;
+var exec = require("child_process").spawn;
 
 function runCommand(command, args, done) {
     if(typeof args === "function") {
         done = args;
         args = "";
     }
 
-    exec("p4 " + command + " " + (args || ""), function(err, stdOut, stdErr) {
-        if(err) return done(err);
-        if(stdErr) return done(new Error(stdErr));
+    if(!Array.isArray(args)) {
+        args = [args];
+    }
+    args.unshift(command);
+
+    var child = spawn("p4", args);
+    var stdOutBuf = "";
+    var stdErrBuf = "";
+
+    child.stdout.on("data", (data) => stdOutBuf += data);
+    child.stderr.on("data", (data) => stdErrBuf += data)
+    child.on("exit", (code) => {
+        if (code !== 0) {
+            return done(new Error(`p4 subcommand exited with return code ${}`));
+        }
+
+        if (stdErrBuf.length > 0) {
+            return done(new Error(stdErrBuf));
+        }
 
-        done(null, stdOut);
+        done(null, stdOutBuf);
     });
 }
 
 function edit(path, done) {
     runCommand("edit", path, done);
diff --git a/package.json b/package.json
index f4480d5..3b56993 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
 {
     "name": "p4",
-    "version": "0.0.6",
+    "version": "0.0.7",
     "description": "A small utility library for dealing with Perforce",
     "main": "p4.js",
     "author": "Nate Long <long.nathaniel@gmail.com>",
     "license": "MIT",
     "repository": {

Vulnerable code: var exec = require("child_process").exec;
    exec("p4 " + command + " " + (args || ""), function(err, stdOut, stdErr) {
        if(err) return done(err);
        if(stdErr) return done(new Error(stdErr));
        done(null, stdOut);
    "version": "0.0.6",
Fixed code: var exec = require("child_process").spawn;
    if(!Array.isArray(args)) {
        args = [args];
    }
    args.unshift(command);

    var child = spawn("p4", args);
    var stdOutBuf = "";
    var stdErrBuf = "";

    child.stdout.on("data", (data) => stdOutBuf += data);
    child.stderr.on("data", (data) => stdErrBuf += data)
    child.on("exit", (code) => {
        if (code !== 0) {
            return done(new Error(`p4 subcommand exited with return code ${}`));
        }

        if (stdErrBuf.length > 0) {
            return done(new Error(stdErrBuf));
        }
        done(null, stdOutBuf);
    "version": "0.0.7",