Skip to content

fix(security): shell-escape repo arg in buildGithubMergeCommand (sibling to #403)#407

Merged
bakeb7j0 merged 1 commit intokahuna/390-bug-drainfrom
fix/security-pr-merge-buildmergecmd-repo-escape
May 6, 2026
Merged

fix(security): shell-escape repo arg in buildGithubMergeCommand (sibling to #403)#407
bakeb7j0 merged 1 commit intokahuna/390-bug-drainfrom
fix/security-pr-merge-buildmergecmd-repo-escape

Conversation

@bakeb7j0
Copy link
Copy Markdown
Contributor

@bakeb7j0 bakeb7j0 commented May 6, 2026

Summary

Sibling fix to PR #403. The original code-reviewer finding flagged BOTH repoFlag in enqueuePullRequestViaGraphQL AND the repo arg in buildGithubMergeCommand as shell-injection surfaces. PR #403 fixed only the former (via runArgv); this PR closes the buildGithubMergeCommand path with shellEscape() — matching the existing pattern used for squashMessage and tempFile two lines above.

Surfaced by re-running the trust-score gate code-reviewer pass after PR #403 merged.

Changes

  • lib/adapters/pr-merge-github.ts:161 — wrap repo in shellEscape() to match squashMessage/tempFile pattern
  • lib/adapters/pr-merge-github.test.ts — adds regression test injecting sec/repo'; echo PWNED; #
  • tests/pr_merge.test.ts — updates two assertions that expected unquoted form

Tests

  • ✅ 2239 pass / 0 fail / 3 skip (full suite)
  • ✅ 17 pass in pr-merge-github.test.ts
  • ./scripts/ci/validate.sh green (76/76 tools)

Defence-in-depth note

The schema layer (repoOptionalSchema) already rejects shell metacharacters at the handler boundary, so this is not exploitable in practice. But every other parts.push() in this function shell-escapes; the inconsistency was a regression risk for any future code that bypasses the schema (e.g. internal callers, refactors).

Closes #390 (gate hotfix sibling)

Sibling fix to PR #403. The original critical finding noted both
repoFlag in enqueuePullRequestViaGraphQL AND the repo arg in
buildGithubMergeCommand. PR #403 fixed only the former (via runArgv);
this PR closes the buildGithubMergeCommand path with shellEscape() —
matching the existing pattern for squashMessage and tempFile two
lines above.

Adds a regression test that injects 'sec/repo'\''; echo PWNED; #' as
the repo arg and verifies the dangerous chars only appear inside
single-quoted argv tokens (or inside the '\\'' escape sequence).

Updates two existing tests that asserted the unquoted form to use
unquote() / .replace(/'/g, '').
@bakeb7j0 bakeb7j0 merged commit 404ccdc into kahuna/390-bug-drain May 6, 2026
1 check failed
@bakeb7j0 bakeb7j0 deleted the fix/security-pr-merge-buildmergecmd-repo-escape branch May 6, 2026 01:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants