bashgithub-actions

Escaping freeform text in github actions to safely populate shell variables


I have a GitHub Action that adds a prefix to the PR's title if its branch name has a specific prefix. It throws an error (or otherwise misbehaves) if github.event.pull_request.title contains unescaped characters like backticks, $s, quotes (of the same kind that surround the substitution point), etc.

How can I safely substitute GitHub Action variables into my script if I don't control their content?

title="${{ github.event.pull_request.title }}"

if [[ ${{ github.head_ref }} = hotfix/* ]] && [[ $title != hotfix:* ]]; then
  echo "Marking as hotfix."
  gh pr edit ${{ env.PR_NUMBER }} --title "hotfix: ${title}"
fi

Solution

  • Ideally, use a templating system that performs shell-safe escaping itself; it's a common feature.

    Unfortunately, the docs for GitHub actions don't indicate that it supports that (very common) feature -- but it does support JSON, so you can use that:

    read_nullsep() {
      local arg
      for arg; do
        IFS= read -r -d '' "$arg" || return
      done
    }
    
    read_nullsep title head_ref pr_number < <(jq -j '(tostring | gsub("\u0000"; ""), "\u0000")' <<'EOF'
    ${{ toJSON(github.event.pull_request.title) }}
    ${{ toJSON(github.head_ref) }}
    ${{ toJSON(env.PR_NUMBER) }}
    EOF
    ) || { echo "Error decoding metadata" >&2; exit 1; }
    
    if [[ $head_ref = hotfix/* ]] && [[ $title != hotfix:* ]]; then
      echo "Marking as hotfix."
      gh pr edit "$pr_number" --title "hotfix: ${title}"
    fi
    

    Some implementation notes: