Skip to content

Commit 02c76d3

Browse files
committed
fix: harden gstack-slug against shell injection via eval
Whitelist safe characters (a-zA-Z0-9._-) in SLUG and BRANCH output to prevent shell metacharacter injection when used with eval. Only affects self-hosted git servers with lax naming rules — GitHub and GitLab enforce safe characters already. Defense-in-depth.
1 parent 716e4c9 commit 02c76d3

2 files changed

Lines changed: 13 additions & 2 deletions

File tree

bin/gstack-slug

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
# Usage: eval $(gstack-slug) → sets SLUG and BRANCH variables
44
# Or: gstack-slug → prints SLUG=... and BRANCH=... lines
55
set -euo pipefail
6-
SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-')
7-
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-')
6+
# tr -cd strips any shell metacharacters (;$`|&! etc) from git-derived values
7+
# to prevent injection via eval $(gstack-slug). See: #133
8+
SLUG=$(git remote get-url origin 2>/dev/null | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|;s|.*[:/]\([^/]*/[^/]*\)$|\1|' | tr '/' '-' | tr -cd 'a-zA-Z0-9._-')
9+
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | tr '/' '-' | tr -cd 'a-zA-Z0-9._-')
810
echo "SLUG=$SLUG"
911
echo "BRANCH=$BRANCH"

test/skill-validation.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,15 @@ describe('gstack-slug', () => {
793793
expect(lines[0]).toMatch(/^SLUG=.+/);
794794
expect(lines[1]).toMatch(/^BRANCH=.+/);
795795
});
796+
797+
test('output values contain only safe characters (no shell metacharacters)', () => {
798+
const result = Bun.spawnSync([SLUG_BIN], { cwd: ROOT, stdout: 'pipe', stderr: 'pipe' });
799+
const slug = result.stdout.toString().match(/SLUG=(.*)/)?.[1] ?? '';
800+
const branch = result.stdout.toString().match(/BRANCH=(.*)/)?.[1] ?? '';
801+
// Only alphanumeric, dot, dash, underscore are allowed (#133)
802+
expect(slug).toMatch(/^[a-zA-Z0-9._-]+$/);
803+
expect(branch).toMatch(/^[a-zA-Z0-9._-]+$/);
804+
});
796805
});
797806

798807
// --- Test Bootstrap validation ---

0 commit comments

Comments
 (0)