flawopen.com/Безопасность GitHub Actions/Инъекция скриптов workflow
Как возникает инъекция скриптов GitHub Actions и как её предотвратить?
Workflow может превратить данные в синтаксис shell, если вставит заголовок issue или поле pull request в скрипт до запуска Bash. Это как принтер бейджей, который принимает имя за команду. Передавайте значение через переменную окружения и заключайте подстановку в кавычки. Тогда Bash получает её отдельно от скрипта. Последствия зависят от токена, секретов, runner и события.
${{ ... }} до запуска shell. В run: ввод может попасть в исходный текст скрипта.env: передаёт значение как данные процесса. Кавычьте shell-подстановку, не используйте eval и динамические скрипты.Причина: данные вставляются до разбора shell
GitHub подставляет выражения до запуска shell для шага run. Недоверенный заголовок в исходном тексте может изменить программу shell. Значение через env: отделено от текста скрипта; в кавычках это аргумент обычной команды. Это не защищает последующее применение через eval, другой интерпретатор или инструмент, трактующий аргументы как код. GitHub относит поля событий к потенциально контролируемому атакующим вводу.
# ОПАСНО: данные события становятся частью созданного shell-скрипта
name: Issue Triage
on:
issues:
types: [opened]
permissions:
contents: read
jobs:
triage:
runs-on: ubuntu-latest
steps:
- name: Print issue title
run: |
printf 'Title: %s\n' "${{ github.event.issue.title }}"
# Безопаснее: передать значение события через окружение
name: Issue Triage
on:
issues:
types: [opened]
permissions:
contents: read
jobs:
triage:
runs-on: ubuntu-latest
steps:
- name: Print issue title
env:
ISSUE_TITLE: ${{ github.event.issue.title }}
run: |
printf 'Title: %s\n' "$ISSUE_TITLE"
Краткая цепочка атаки
Пользователь управляет полем события
Например, заголовком публичной issue или pull request либо именем ветки, которое принимает workflow.
Workflow вставляет его в shell-код
Прямое выражение ${{ github.event... }} в run: вычисляется до разбора скрипта Bash.
Shell разбирает изменённую программу
Если значение меняет синтаксис, команды выполняются с правами процесса job. В кавычках оно остаётся данными аргумента.
Права job определяют последствия
Скомпрометированный job достигает только доступных ему ресурсов: прав GITHUB_TOKEN, секретов и runner. Проверяйте issue-события и pull_request_target.
Контрольный список защиты
- ✓Не вставляйте недоверенные значения
github.eventвrun:. Передавайте черезenv:и заключайте в кавычки, например"$ISSUE_TITLE". - ✓Не передавайте их в
eval, генерируемые скрипты, строки shell-команд и инструменты, трактующие аргументы как код или параметры. - ✓Задайте ограниченные
permissions:; право записи оставьте только нужному job. - ✓Считайте
pull_request_targetиworkflow_runпривилегированной границей. Не извлекайте, не собирайте и не запускайте там недоверенный код или артефакты PR. - ✓Не записывайте недоверенные многострочные данные в
GITHUB_ENVилиGITHUB_PATH. GitHub защищаетGITHUB_*иRUNNER_*, но другие значения могут влиять на следующие шаги. - ✓Фиксируйте сторонние Actions на проверенных полных SHA, используйте изолированные одноразовые runner и включите CodeQL для workflow Actions.
Первичные источники
- Документация GitHub — инъекции скриптов
- Документация GitHub — безопасное использование
- Документация GitHub — безопасность pull_request_target
- Документация GitHub — команды workflow и GITHUB_ENV
- Документация GitHub — права GITHUB_TOKEN