mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
On Unix/macOS, pass args to spawn to avoid escaping issues
This commit is contained in:
parent
486a4b8f68
commit
7e72ae7d3d
1 changed files with 27 additions and 6 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { spawnSync, spawn } from "child_process";
|
import { spawn, execSync } from "child_process";
|
||||||
|
|
||||||
function escapeArg(arg) {
|
function escapeArg(arg) {
|
||||||
// Shell metacharacters that need escaping
|
// Shell metacharacters that need escaping
|
||||||
|
|
@ -16,18 +16,39 @@ function escapeArg(arg) {
|
||||||
|
|
||||||
function buildCommand(command, args) {
|
function buildCommand(command, args) {
|
||||||
const escapedArgs = args.map(escapeArg);
|
const escapedArgs = args.map(escapeArg);
|
||||||
|
|
||||||
return `${command} ${escapedArgs.join(" ")}`;
|
return `${command} ${escapedArgs.join(" ")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function safeSpawnSync(command, args, options = {}) {
|
function resolveCommandPath(command) {
|
||||||
const fullCommand = buildCommand(command, args);
|
// command will be "npm", "yarn", etc.
|
||||||
return spawnSync(fullCommand, { ...options, shell: true });
|
// Use 'command -v' to find the full path
|
||||||
|
const fullPath = execSync(`command -v ${command}`, {
|
||||||
|
encoding: "utf8",
|
||||||
|
shell: true,
|
||||||
|
}).trim();
|
||||||
|
|
||||||
|
if (!fullPath) {
|
||||||
|
throw new Error(`Command not found: ${command}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function safeSpawn(command, args, options = {}) {
|
export async function safeSpawn(command, args, options = {}) {
|
||||||
const fullCommand = buildCommand(command, args);
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const child = spawn(fullCommand, { ...options, shell: true });
|
// Windows requires shell: true because .bat and .cmd files are not executable
|
||||||
|
// without a terminal. On Unix/macOS, we resolve the full path first, then use
|
||||||
|
// array args (safer, no escaping needed).
|
||||||
|
// See: https://nodejs.org/api/child_process.html#child_processspawncommand-args-options
|
||||||
|
let child;
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
const fullCommand = buildCommand(command, args);
|
||||||
|
child = spawn(fullCommand, { ...options, shell: true });
|
||||||
|
} else {
|
||||||
|
const fullPath = resolveCommandPath(command);
|
||||||
|
child = spawn(fullPath, args, options);
|
||||||
|
}
|
||||||
|
|
||||||
child.on("close", (code) => {
|
child.on("close", (code) => {
|
||||||
resolve({
|
resolve({
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue