From ffb56b556de34fdac32003aa5965c502e7c0d002 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Mon, 13 Apr 2026 09:33:01 -0700 Subject: [PATCH] =?UTF-8?q?fix(security):=20shell=20injection=20in=20bin/?= =?UTF-8?q?=20scripts=20=E2=80=94=20use=20env=20vars=20instead=20of=20inte?= =?UTF-8?q?rpolation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gstack-settings-hook interpolated $SETTINGS_FILE directly into bun -e double-quoted blocks. A path containing quotes or backticks breaks the JS string context, enabling arbitrary code execution. Replace direct interpolation with environment variables (process.env). Same fix applied to gstack-team-init which had the same pattern. Systematic audit confirmed only these two scripts were vulnerable — all other bin/ scripts already use stdin piping or env vars. Closes #858 Co-Authored-By: Gus --- bin/gstack-settings-hook | 10 +++++----- bin/gstack-team-init | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bin/gstack-settings-hook b/bin/gstack-settings-hook index 93a537f0..21445a14 100755 --- a/bin/gstack-settings-hook +++ b/bin/gstack-settings-hook @@ -26,10 +26,10 @@ fi case "$ACTION" in add) - bun -e " + GSTACK_SETTINGS_PATH="$SETTINGS_FILE" GSTACK_HOOK_CMD="$HOOK_CMD" bun -e " const fs = require('fs'); - const settingsPath = '$SETTINGS_FILE'; - const hookCmd = $(printf '%s' "$HOOK_CMD" | bun -e "process.stdout.write(JSON.stringify(require('fs').readFileSync('/dev/stdin','utf8')))"); + const settingsPath = process.env.GSTACK_SETTINGS_PATH; + const hookCmd = process.env.GSTACK_HOOK_CMD; let settings = {}; try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); } catch {} @@ -55,9 +55,9 @@ case "$ACTION" in ;; remove) [ -f "$SETTINGS_FILE" ] || exit 0 - bun -e " + GSTACK_SETTINGS_PATH="$SETTINGS_FILE" bun -e " const fs = require('fs'); - const settingsPath = '$SETTINGS_FILE'; + const settingsPath = process.env.GSTACK_SETTINGS_PATH; let settings = {}; try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); } catch { process.exit(0); } diff --git a/bin/gstack-team-init b/bin/gstack-team-init index 1fc08ea9..256735f8 100755 --- a/bin/gstack-team-init +++ b/bin/gstack-team-init @@ -139,9 +139,9 @@ HOOK_EOF # Add hook to project-level settings.json if command -v bun >/dev/null 2>&1; then - bun -e " + GSTACK_SETTINGS_PATH="$SETTINGS" bun -e " const fs = require('fs'); - const settingsPath = '$SETTINGS'; + const settingsPath = process.env.GSTACK_SETTINGS_PATH; let settings = {}; try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); } catch {}