flawopen.com/Segurança do GitHub Actions/Injeção de scripts em workflows
Como ocorre a injeção de scripts no GitHub Actions e como evitá-la?
Um workflow pode transformar dados em sintaxe shell ao inserir um título de issue ou campo de pull request no script antes de iniciar o Bash. É como uma impressora de crachás que confunde o nome com instruções. Passe o valor por uma variável de ambiente e coloque a expansão entre aspas ao usá-lo como dado; assim, o Bash recebe o valor separado do script. O impacto ainda depende do token, dos secrets, do runner e do evento.
${{ ... }} antes de o shell iniciar. Em um bloco run:, isso pode inserir entrada no código-fonte do script.env: o passa como dado do processo. Coloque a expansão do shell entre aspas e evite eval ou gerar outro script.Causa raiz: dados entram antes da análise do shell
O GitHub expande expressões antes de iniciar o shell de uma etapa run. Se um título não confiável for interpolado diretamente no script, seus caracteres podem alterar o programa shell em vez de permanecerem dados. Um valor passado por env: fica separado do texto do script; entre aspas, sua expansão permanece um argumento para comandos comuns. Isso não torna seguro o uso posterior com eval, outro interpretador ou uma ferramenta que interprete argumentos como código. O GitHub documenta campos de eventos não confiáveis como entrada controlável por atacantes.
# INSEGURO: dados do evento passam a fazer parte do script shell gerado
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 }}"
# Mais seguro: passe o valor do evento pelo ambiente
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"
Caminho de ataque em resumo
Um usuário controla um campo do evento
Por exemplo, o título de uma issue pública, o título de um pull request ou o nome de uma branch torna-se entrada do workflow.
O workflow o insere no código-fonte shell
Uma expressão direta ${{ github.event... }} dentro de run: é expandida antes de o Bash analisar o script.
O shell interpreta o programa alterado
Se o valor mudar a sintaxe do shell, comandos podem rodar com a identidade do processo do job. Se permanecer dado e for usado como argumento entre aspas, não há essa injeção.
As permissões do job definem o impacto
Um job comprometido só alcança recursos expostos àquela execução, incluindo as permissões efetivas de GITHUB_TOKEN, secrets disponíveis e recursos do runner. Revise com cuidado eventos de issues e pull_request_target.
Checklist de proteção
- ✓Nunca interpole valores não confiáveis de
github.eventdiretamente em scriptsrun:. Passe-os porenv:e use expansões entre aspas, como"$ISSUE_TITLE". - ✓Mantenha valores não confiáveis fora de
eval, scripts gerados, strings de comandos shell e ferramentas que interpretem argumentos como código ou opções. - ✓Defina
permissions:restritivas no workflow ou job e conceda escrita apenas ao job que precisa dela. - ✓Trate
pull_request_targeteworkflow_runcomo limites privilegiados. Não faça checkout, build ou execução de código ou artefatos não confiáveis nesse contexto. - ✓Não escreva dados multiline não confiáveis em
GITHUB_ENVouGITHUB_PATH. O GitHub bloqueia a sobrescrita deGITHUB_*eRUNNER_*, mas outros valores ainda podem afetar etapas seguintes. - ✓Fixe actions de terceiros por SHA completo revisado, use runners isolados e efêmeros para jobs não confiáveis e habilite a análise CodeQL para workflows Actions.
Fontes primárias
- GitHub Docs — injeção de scripts
- GitHub Docs — referência de uso seguro
- GitHub Docs — uso seguro de pull_request_target
- GitHub Docs — comandos de workflow e GITHUB_ENV
- GitHub Docs — permissões de GITHUB_TOKEN