From 657b12273656eeff1b72e2808aefd5deaf17494b Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Wed, 15 Jul 2026 03:24:46 +0000 Subject: [PATCH] fix(ci): harden branch-cleanup.yml against Actions injection (sync from Template-Generic) --- .mokogit/workflows/branch-cleanup.yml | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/.mokogit/workflows/branch-cleanup.yml b/.mokogit/workflows/branch-cleanup.yml index e0e293f..183b1df 100644 --- a/.mokogit/workflows/branch-cleanup.yml +++ b/.mokogit/workflows/branch-cleanup.yml @@ -5,7 +5,7 @@ # FILE INFORMATION # DEFGROUP: MokoGIT.Workflow # INGROUP: MokoCLI.Universal -# REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli +# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic # PATH: /.mokogit/workflows/branch-cleanup.yml # VERSION: 01.00.00 # BRIEF: Delete feature branches after PR merge @@ -30,13 +30,25 @@ jobs: steps: - name: Delete source branch + # SECURITY: the PR head ref is attacker-controllable. Pass it (and the + # repo/token) through env so the Actions engine cannot splice it into the + # shell source, and validate it to a safe charset before use. + env: + MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }} + REPO: ${{ github.repository }} + API_BASE: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} + BRANCH: ${{ github.event.pull_request.head.ref }} run: | - BRANCH="${{ github.event.pull_request.head.ref }}" - API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches" - ENCODED=$(php -r "echo rawurlencode('${BRANCH}');") + set -euo pipefail + if ! printf '%s' "${BRANCH}" | grep -Eq '^[A-Za-z0-9._/-]+$'; then + echo "::error::unsafe branch name; refusing to proceed"; exit 1 + fi + API="${API_BASE}/api/v1/repos/${REPO}/branches" + # URL-encode the branch name's slashes (no PHP dependency on the runner) + ENCODED=$(printf '%s' "${BRANCH}" | sed 's|/|%2F|g') STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \ - -H "Authorization: token ${{ secrets.MOKOGIT_TOKEN }}" \ + -H "Authorization: token ${MOKOGIT_TOKEN}" \ "${API}/${ENCODED}" 2>/dev/null || true) if [ "$STATUS" = "204" ]; then