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