Skip to content

bug(security): pr-wait-ci-github.ts repoFlag shell-injection (defence-in-depth) #409

@bakeb7j0

Description

@bakeb7j0

Summary

Pre-existing shell-injection surface in lib/adapters/pr-wait-ci-github.ts. The repoFlag helper interpolates repo raw into the shell command string:

function repoFlag(repo: string | undefined): string {
  return repo !== undefined ? ` --repo ${repo}` : '';
}

The result is concatenated into commands like gh pr view ${number} --json statusCheckRollup,url${repoFlag(repo)} and passed to exec() (which calls execSync directly).

This is the same injection class as PR #403/#407.

Active exploitability: Mitigated by repoOptionalSchema (regex blocks shell metacharacters at the handler boundary). This is a defence-in-depth fix.

Implementation Steps

  1. Update lib/adapters/pr-wait-ci-github.ts. Two options:

    Option A (minimal): import shellEscape and wrap the value:

    import { shellEscape } from '../shared/shell-escape.js';
    
    function repoFlag(repo: string | undefined): string {
      return repo !== undefined ? ` --repo ${shellEscape(repo)}` : '';
    }

    Option B (preferred): migrate the call site to use runArgv (argv-array form) instead of string-template + exec(). Same pattern as PR fix(security): eliminate shell injection in pr_merge GraphQL fallback #403's fix in pr-merge-github.ts.

  2. Add a regression test in lib/adapters/pr-wait-ci-github.test.ts (or wherever this adapter is tested) injecting a hostile repo value.

Test Procedures

  1. Run existing tests for pr-wait-ci-github.ts — all should pass.
  2. Inject hostile repo value, verify no breakout.
  3. Run full suite — confirm no regressions.

Acceptance Criteria

  • pr-wait-ci-github.ts:repoFlag shell-escapes repo (or migrates to runArgv)
  • New regression test asserts shell-injection is contained
  • Full test suite passes (no regressions)
  • Audit other adapters in lib/adapters/ for the same ${repo} interpolation pattern (light grep) and either fix or document any others found

Dependencies

Metadata

Field Value
Repository Wave-Engineering/mcp-server-sdlc
Surfaced by code-reviewer trust-score gate (plan #390 audit byproduct)

Metadata

Metadata

Assignees

No one assigned

    Labels

    type::bugSomething is not working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions