O GitHub Actions tem sido muito explorado em diversos ataques à Supply chain ultimamente, e as configurações incorretas de workflows têm desempenhado papéis importantes. É perigoso ir sozinho! Pegue esta (checklist).

Por que existem tantos problemas de segurança com o GitHub Actions?
O GitHub Actions, sistema de CI/CD e automação integrado do GitHub, não possui segurança inerentemente fraca, mas certamente oferece muitas maneiras de cometer erros graves.
A plataforma funciona conforme projetado, mas as configurações padrão são geralmente definidas para conveniência e flexibilidade, não para segurança. pull_request_target existe por uma razão, e tags mutáveis são certamente convenientes. Mas essas decisões de design criaram uma superfície de ataque que só se tornou óbvia mais tarde.
O GitHub Actions é também o sistema de CI/CD padrão para a maioria dos projetos de código aberto, e assumir o controle de um projeto de código aberto permite que hackers atinjam as vítimas mais a jusante. Workflows frequentemente contêm credenciais que publicam para npm e PyPI, então um workflow comprometido pode enviar uma versão maliciosa de um pacote, e todo desenvolvedor que instala esse pacote também o recebe.
Outra razão pela qual continuamos a ver tantos dos mesmos vetores aparecendo em incidentes é porque a superfície de ataque tem sido bem documentada em pesquisas públicas há anos. Atacantes às vezes apenas escaneiam repositórios procurando por essas configurações incorretas para encontrar alvos de ataque fáceis (veja prt-scan). O GitHub está priorizando proteções mais fortes no próximo ano para proteger melhor os usuários, mas grande parte da responsabilidade ainda recai sobre o usuário para configurar o GitHub de forma segura e correta.
Seguir todas as melhores práticas não tornará seus workflows à prova de balas. Embora você não possa se proteger totalmente de um mantenedor comprometido ou de um zero-day na infraestrutura do GitHub, você pode fechar muitos dos vetores que os atacantes estão explorando ativamente ultimamente, e tornar seus repositórios um alvo mais difícil do que a maioria.
Melhores práticas para manter seus workflows do GitHub Actions seguros
Comece aqui. Se você fizer apenas cinco coisas desta checklist:
- Fixe todas as ações de terceiros a um SHA de commit completo
- Defina as permissões padrão
GITHUB_TOKENcomo somente leitura - Nunca
pull_request_targetem repositórios públicos - Nunca interpole
${{ github.* }}diretamente emrun:steps - Use OIDC para credenciais da Cloud em vez de Secrets de longa duração
Mas recomendamos que você leia a checklist em detalhes, onde explicamos todos os nossos conselhos de segurança para o GitHub Actions e por que você precisa deles. Confira também as ferramentas na parte inferior, que o ajudarão a implementar e aplicar essas melhores práticas.
Configuração de trigger
1. Nunca use pull_request_target em repositórios públicos
pull_request_target Existe para permitir que os fluxos de trabalho acionados por PRs de forks sejam executados com acesso aos secrets do repositório base. Permite-lhe etiquetar ou comentar automaticamente PRs de colaboradores externos. É uma boa ideia, mas o acesso aos secrets isto perigoso. Por predefinição, o fluxo de trabalho é executado a partir do ramo predefinido do repositório base, pelo que nenhum código do fork é executado, a menos que o selecione explicitamente. O gatilho é seguro nesse estado predefinido. O risco surge quando se combina o gatilho com a obtenção do código do fork.
Ao contrário do padrão pull_request trigger, pull_request_target é executado no contexto do repositório base, independentemente da origem do PR. Qualquer pessoa pode abrir um PR num repositório público. Se o seu fluxo de trabalho for acionado por esse PR, mesmo que este não tenha sido integrado, quaisquer secrets referenciados no fluxo de trabalho são carregados no ambiente do executor e tornam-se acessíveis a qualquer código que seja executado nesse executor. A isto chama-se um «pwn request». O script do atacante pode facilmente ler qualquer um deles através de uma consulta ao ambiente, como os.environ.get('MY_SECRET') e enviá-los de volta a um atacante sem deixar evidências.
Se você precisar disso em um repositório privado, exija que os PRs de contribuidores de primeira viagem obtenham uma aprovação de um mantenedor antes que possam acionar quaisquer workflows. O GitHub oferece suporte nativo a isso em Settings > Actions > Fork pull request workflows.
A partir de 18 de junho de 2026, ações/finalização da compra A versão 7 bloqueia, por predefinição, padrões comuns de pedidos de pwn em pull_request_target fluxos de trabalho, recusando-se a obter o código de um PR de fork, a menos que se defina explicitamente allow-unsafe-pr-checkout: true.
Na prática: O ataque Trivy de março de 2026 veio da exploração de pull_request_target. começou a escanear o GitHub especificamente por repositórios com pull_request_target ativado e abriu algumas centenas de PRs em cerca de um dia.
2. Evite workflow_run em repositórios públicos
workflow_run permite encadear workflows para que um workflow downstream seja acionado quando um upstream for concluído. O problema é que o workflow downstream é executado com permissões de escrita e acesso a Secrets, independentemente do que acionou o upstream, incluindo um fork PR de um contribuidor externo.
Se um upstream pull_request O workflow é vulnerável a injeção de script, um invasor pode corromper o artefato de saída via um PR. O workflow downstream então consome conteúdo controlado pelo invasor em um contexto privilegiado com acesso a Secrets, de modo que o conteúdo controlado pelo invasor de um PR não confiável agora alcançou um workflow com acesso a Secrets através de um salto extra. O caminho de ataque é mais longo do que pull_request_target mas chega ao mesmo lugar.
A melhor correção é evitar o padrão. Se um deploy só precisa acontecer em pushes para main, dispare-o diretamente com um push em main em vez de encadeá-lo através de workflow_run. Se você realmente precisa de workflow_run, verifique github.event.workflow_run.event antes de tomar qualquer ação privilegiada. Se o gatilho upstream foi um pull_request em vez de um push de um mantenedor, desista antes de fazer o deploy ou escrever qualquer coisa.
jobs:
deploy:
if: github.event.workflow_run.event == 'push'
Aikido sinalizar workflow_run workflows que executam ações privilegiadas sem a verificação de evento, se você deseja detecção automatizada em todo o seu repositório.
ações/finalização da compra A v7 também bloqueia checkouts inseguros de PRs em fork em workflow_run fluxos de trabalho em que workflow_run.event é um pull_request* evento, com o mesmo allow-unsafe-pr-checkout: true exclusão.
3. Audite workflows usando outros gatilhos privilegiados
Além de pull_request_target e workflow_run, fique atento a outros gatilhos que são executados com acesso a Secrets. Estes incluem issue_comment, issues, pull_request_review, e pull_request_review_comment. Como todos são executados com acesso a Secrets, eles podem ser influenciados por contribuidores externos. As mesmas regras de injeção de script se aplicam, que é nunca interpolar valores desses eventos diretamente em run: steps. Falaremos mais sobre isso na próxima seção.
4. Não permita que os fluxos de trabalho de bifurcação escrevam no cache do seu ramo predefinido
Fluxos de trabalho acionados por pull_request_target e workflow_run Ambos têm acesso de escrita ao cache partilhado com o ramo predefinido. Um colaborador que consiga desencadear qualquer um desses eventos pode corromper esse cache, introduzindo dados que afetem fluxos de trabalho subsequentes não relacionados, executados no ramo predefinido. Analise o que esses fluxos de trabalho armazenam em cache e consomem, e evite utilizar dados armazenados em cache provenientes de execuções privilegiadas entre ramos como entrada para etapas sensíveis.
Tratamento de entrada não confiável
5. Evitar a injeção de scripts, tratando todos os nomes de ramos, títulos de PR, mensagens de commit e corpos de issues como entradas não confiáveis
Este é o mesmo princípio da injeção de SQL. Valores controlados pelo usuário que acabam em um comando shell são interpretados como código, não como dados, portanto, nunca interpole github.* valores diretamente em run: steps. A correção é atribuir o valor a uma variável de ambiente primeiro e, em seguida, referenciar essa variável no script shell:
# vulnerable
- run: echo "Branch is ${{ github.head_ref }}"
# safe
- run: echo "Branch is $BRANCH"
env:
BRANCH: ${{ github.head_ref }}
Quando o valor é atribuído a uma variável de ambiente, o shell o lê como uma string em tempo de execução, em vez de interpretá-lo como sintaxe em tempo de análise. Isso se aplica a qualquer coisa originada de entrada controlada pelo usuário: github.head_ref, github.event.pull_request.title, github.event.issue.body, github.event.commits[0].message, e valores de contexto semelhantes. Um bom scanner SAST como Aikido detectará isso e fornecerá a correção em um pull request.
Na prática: No ataque Ultralytics, um atacante nomeou um branch com um comando curl que um workflow interpolou diretamente em um run: step, executando-o como código. O ataque Nx/s1ngularity, primeiramente detectado pela Aikido Security, combinou isso com pull_request_target, onde um PR para um branch desatualizado acionou um workflow vulnerável que vazou um GITHUB_TOKEN com permissões de leitura/escrita, que foi então usado para publicar pacotes npm maliciosos.
6. No caso de agentes de IA em fluxos de trabalho personalizados, utilize tokens de leitura exclusiva e evite incluir dados brutos introduzidos pelo utilizador nos prompts
Agentes de IA executados em workflows do GitHub Actions têm o mesmo acesso a Secrets que qualquer outro step. Se um agente processar títulos de issues, descrições de PRs ou mensagens de commit como parte de seu prompt, um atacante pode inserir instruções nesse texto e manipular o agente para que ele execute ações privilegiadas, como modificar arquivos ou exfiltrar dados por meio de quaisquer ferramentas às quais ele tenha acesso. Como não há como prevenir a injeção de prompt em LLMs, não permita que agentes de IA tenham acesso além da leitura, e não permita que eles recebam títulos de issues brutos, descrições de PRs ou mensagens de commit como entrada de prompt.
Na prática: Pesquisadores da Aikido demonstraram isso com PromptPwnd: um título de issue malicioso inserido em um workflow Gemini CLI fez com que o agente escrevesse Secrets do repositório em um thread de issue público usando seu próprio gh acesso à ferramenta.
7. Tratar os resultados gerados por modelos de linguagem de grande escala (LLM) como dados de entrada não fiáveis
Quando um fluxo de trabalho usa um LLM para gerar um comando, script ou caminho de arquivo e passa essa saída diretamente para um run: passo, isso cria o mesmo risco de injeção que interpolar um nome de branch ou título de PR. A saída do LLM não é garantida como segura, e um atacante que pode influenciar o prompt pode influenciar o que é executado. Como discutimos no item anterior sobre injeção de prompt, atribua a saída do LLM a uma variável de ambiente primeiro, valide-a sempre que possível e nunca a direcione diretamente para um comando shell.
8. Nunca grave dados não confiáveis em GITHUB_ENV ou GITHUB_PATH
Escrever em GITHUB_ENV define variáveis de ambiente para todos os passos subsequentes no job. Escrever em GITHUB_PATH adiciona entradas ao início do PATH do sistema para todos os passos subsequentes. Se conteúdo não confiável atingir qualquer um dos arquivos, um atacante pode definir variáveis de ambiente arbitrárias, como NODE_OPTIONS que acionam a execução de código. Eles também poderiam injetar um binário de malware no início do PATH que é chamado no lugar de uma ferramenta confiável. O padrão vulnerável é um fluxo de trabalho que baixa um artefato ou lê entrada controlada pelo usuário e o escreve diretamente em $GITHUB_ENV sem sanitização. Trate qualquer coisa escrita nesses arquivos com a mesma cautela que um run: passo.
Manipulação de artefatos
9. Extraia os artefactos para um diretório temporário, como /tmp em vez do workspace, para evitar sobrescrever arquivos de fluxo de trabalho
Extrair um artefato diretamente para o workspace poderia permitir que um arquivo com conteúdo malicioso sobrescreva arquivos de fluxo de trabalho, scripts ou ferramentas dos quais os passos subsequentes dependem. Extrair para /tmp ou outro diretório isolado mantém o conteúdo do artefato longe de qualquer coisa que seu fluxo de trabalho trate como confiável. O GitHub também suporta verificação de digest SHA256 se você precisar de garantias de integridade mais fortes.
10. Excluir ficheiros secretos (.env, arquivos de configuração, credenciais) de artefatos carregados e evite path: . padrões que incluem tudo
O path: . padrão em um actions/upload-artifact etapa faz upload de tudo no diretório de trabalho, o que pode incluir .env arquivos, arquivos de configuração com credenciais incorporadas ou Secrets em cache gravados em disco por outras etapas. Seja explícito sobre o que você está fazendo upload para não publicar acidentalmente suas credenciais na internet. Liste diretórios ou tipos de arquivo específicos em vez de varrer todo o workspace, e adicione .env, *.pem, e arquivos semelhantes ao seu .gitignore e padrões de exclusão de artefatos.
Referências de ações mutáveis
11. Associar todas as ações de terceiros a um SHA de commit completo, e não a uma etiqueta ou a um ramo
Tags são úteis como um atalho, mas a desvantagem é que não são estáticas. Tags e branches são mutáveis, o que significa que o proprietário de um repositório pode redirecioná-las para um commit diferente a qualquer momento, e isso é esperado com tags como @main. Ao referenciar uma versão específica com uses: some-action@v3, esperamos que o commit permaneça o mesmo. Mas se a conta do mantenedor da ação for comprometida, um atacante pode redirecionar essa tag para um commit malicioso e todo workflow downstream o pegará na próxima execução sem um PR ou outra indicação. Para evitar isso, a melhor prática é fixar o SHA de commit completo em vez disso: uses: some-action@abc123def456..... Isso, claro, pode ser um pouco chato de lidar, então você pode usar Dependabot, Renovate ou pinact para manter os SHAs fixados atualizados. Lockfiles nativos estão no roadmap do GHA, então, esperamos que esteja disponível até 2027.
Na prática: Em março de 2025, atacantes redirecionaram 76 de 77 tags de versão em aquasecurity/trivy-action para commits maliciosos contendo um infostealer. Todo workflow que referenciava essas tags pelo nome puxou o código malicioso automaticamente.
12. Analisar as ações de terceiros antes da adoção
Antes de adicionar uma uses: linha, dedique dois minutos ao repositório da ação. Verifique se o criador é verificado pelo GitHub, quando o repositório foi mantido pela última vez, quantos contribuidores ele tem e qual é a sua pontuação no OpenSSF Scorecard. Uma ação amplamente utilizada de um único mantenedor não verificado e sem atividade recente é um alvo de alto valor para a tomada de conta.
13. Dê preferência a ações com menos dependências transitivas
Mais dependências o tornam mais vulnerável a ataques à Supply chain, então escolha ações com menos dependências quando houver opções. Uma ação pode referenciar outras ações, e essas dependências transitivas são resolvidas em tempo de execução. Fixar o SHA da sua dependência direta não o protege se ela puxar suas próprias dependências de forma mutável.
Na prática: O comprometimento do tj-actions propagado parcialmente através deste mecanismo. Workflows downstream fixados em tj-actions/changed-files, mas changed-files referenciado transitivamente reviewdog/action-setup por tag mutável, então, quando o reviewdog foi comprometido, todo pipeline downstream executou o código malicioso.
Dependências de pacotes mutáveis
14. Definir explicitamente as versões dos pacotes do npm e do PyPI
Intervalos de versão flutuantes como ^1.2.0 ou >=2.0.0 significam que seu workflow instala a versão mais recente correspondente em tempo de execução. Se um pacote for comprometido e uma nova versão maliciosa for publicada dentro do seu intervalo, seu workflow a puxará automaticamente na próxima execução. Fixe em versões exatas (1.2.3) para que seu workflow instale apenas o que você escolheu explicitamente. Não use intervalos flutuantes.
Na prática: O ataque Ultralytics demonstrou como uma versão de pacote comprometida publicada no PyPI pode atingir workflows não fixados. A primeira release maliciosa ficou ativa por horas antes da detecção, tempo suficiente para afetar builds que puxam dependências flutuantes.
15. Defina uma idade mínima de lançamento, caso o seu gestor de pacotes o suporte (pnpm, yarn)
Mesmo com versões fixadas, um pacote malicioso recém-publicado pode permanecer em uma versão exata para a qual você escolherá fazer upgrade mais tarde. As configurações de idade mínima de release instruem seu gerenciador de pacotes a recusar pacotes publicados há menos de um tempo especificado, geralmente 72 horas, dando tempo à comunidade para detectar e reportar releases maliciosas antes que cheguem aos seus builds. pnpm e yarn suportam isso nativamente, mas npm ainda não. Aikido Safe Chain pode cobrir isso para npm (veja abaixo).
16. Verificar a proveniência das embalagens recorrendo a certificados, sempre que disponíveis
Alguns registros de pacotes agora suportam atestações de proveniência, onde registros criptográficos vinculam um pacote publicado ao commit de origem específico e ao pipeline de build que o produziu. Verificar as atestações antes de instalar um pacote confirma que ele foi construído a partir da fonte que ele alega. npm suporta isso para pacotes publicados via GitHub Actions. Esta ainda é uma prática mais recente e o suporte de ferramentas não está totalmente disponível, mas vale a pena habilitar onde seu registro e gerenciador de pacotes o suportam.
Gerenciamento de Secrets
17. Indique secrets variáveis de ambiente, nunca através de argumentos da linha de comandos
Argumentos de linha de comando são visíveis em listagens de processos, então outros processos no runner com acesso a /proc podem lê-los. Passar um Secret como uma variável de ambiente o mantém fora da tabela de processos. No seu workflow, defina o Secret em um env: bloco e referencie $SECRET_NAME no comando shell em vez de ${{ secrets.MY_SECRET }} inline.
Na prática: tj-actions exfiltraram Secrets imprimindo-os no log (o problema de echo/mascaramento), e o ataque Trivy resultou em um PAT roubado. O gerenciamento de Secrets visa limitar o acesso a Secrets em todo o sistema para que, quando algo der errado, um invasor não consiga sair com credenciais válidas.
18. Delimitar secrets nível do repositório a ambientes específicos do GitHub, sempre que possível
GitHub Environments permitem que você proteja Secrets por trás de regras de proteção de implantação, então um Secret como PROD_DB_PASSWORD é acessível apenas a workflows que visam o ambiente de produção. Sem isso, qualquer workflow no repositório pode ler qualquer Secret de nível de repositório. Você pode configurar isso em Settings > Environments.
19. Definir secrets do fluxo de trabalho ao nível das etapas, e não ao nível das tarefas
Delimitar Secrets aos passos individuais de um job que precisa deles aplica o princípio do menor privilégio para limitar o raio de impacto caso uma ação seja comprometida. Um Secret declarado em um nível de job env: bloco é legível por cada passo nesse job, incluindo ações de terceiros.
Na prática: No ataque Shai-Hulud, tokens com escopo de workflow foram reutilizados entre vítimas. Um escopo mais restrito teria contido o raio de impacto.
20. Utilizar o OIDC para obter credenciais de curta duração na nuvem, em vez de secrets estáticos de longa duração, secrets o fornecedor de serviços na nuvem o suportar (AWS, Azure, GCP)
Credenciais estáticas da Cloud armazenadas como Secrets do GitHub são válidas indefinidamente, então, se forem roubadas, a janela para danos é ampla. O OIDC permite que seu workflow solicite um token de curta duração diretamente da AWS, Azure ou GCP, com escopo para a tarefa e válido por minutos, eliminando credenciais para um atacante roubar. AWS, Azure e GCP oferecem suporte nativo a isso. A configuração envolve estabelecer uma relação de confiança entre seu provedor de Cloud e o endpoint OIDC do GitHub.
21. Limitar a aplicação das regras de editores de confiança do npm a um ficheiro de fluxo de trabalho específico e a um ramo protegido, e não a todo o repositório
Nas configurações de publicação confiável do npm, especifique o nome exato do arquivo de workflow (por exemplo, release.yml) e branch (por exemplo, principal) em vez de confiar no repositório inteiro. Combine isso com regras de proteção de branch que exigem PRs e bloqueiam force pushes, para que nenhum workflow fora desse caminho possa solicitar um token de publicação.
Na prática: No ataque Mini Shai-Hulud TanStack de maio de 2026, um atacante enviou um commit órfão sem histórico de pai para o repositório TanStack/router. Como a regra de editor confiável do npm confiava em todo o repositório em vez de um fluxo de trabalho específico em um branch protegido, o commit acionou um fluxo de trabalho que gerou com sucesso um token de publicação. O atacante o usou para publicar versões maliciosas de 84 pacotes em todo o ecossistema TanStack em uma janela de seis minutos.
22. Exigir aprovação humana nas execuções de fluxos de trabalho que utilizem ambientes de produção
Configure seu Ambiente GitHub para exigir que alguém revise um workflow antes que ele possa acessar os Secrets de um ambiente ou fazer deploy nele. Isso é mais realista para equipes menores ou aquelas que fazem deploys com pouca frequência. Para equipes maiores, a versão mais escalável disso é o OIDC com credenciais de curta duração.
23. Evite imprimir ou exibir valores confidenciais, mesmo na saída de depuração
O GitHub mascara valores de Secrets conhecidos nos logs, mas apenas para correspondências exatas; portanto, se um Secret for codificado em base64 ou dividido em duas chamadas de echo, o mascaramento não funciona. A regra mais segura é simplesmente nunca exibir Secrets. Se você precisar verificar se um Secret está configurado, verifique se há uma string não vazia em vez de imprimir o valor.
Runners
24. Não utilize runners auto-hospedados em repositórios públicos
Qualquer pessoa pode abrir um PR em um repositório público, o que significa que qualquer pessoa pode potencialmente acionar uma execução de workflow. As configurações de aprovação padrão do GitHub para colaboradores de primeira viagem mitigam isso em runners hospedados pelo GitHub, onde o ambiente é efêmero e isolado de qualquer forma. Em um runner auto-hospedado, uma configuração de aprovação incorreta ou excessivamente permissiva significa que o mesmo PR aciona a execução de código em sua infraestrutura. O GitHub recomenda o uso de runners hospedados pelo GitHub para repositórios públicos e o endurecimento da política de aprovação para "exigir aprovação para todos os colaboradores externos".
Na prática: Pesquisadores executaram um ataque de supply chain no PyTorch ao enviar um PR trivial que acionou um workflow em um runner auto-hospedado, obtendo acesso root à máquina.
25. Utilizar runners efémeros em vez de runners estáticos e persistentes
Um runner estático mantém estado entre as tarefas, o que significa que uma tarefa comprometida pode deixar arquivos maliciosos, binários modificados ou caches envenenados que afetam as execuções subsequentes naquela máquina. Runners efêmeros iniciam limpos e são destruídos após cada tarefa. Use o Actions Runner Controller para configurações baseadas em Kubernetes, ou passe a --ephemeral flag ao registrar um runner manualmente.
Na prática: Shai-Hulud registrou runners auto-hospedados persistentes em repositórios comprometidos e os usou como um canal C2 persistente, invisível para o monitoramento de rede porque todo o tráfego fluía por github.com.
26. Restringir a saída da rede do runner a uma lista de permissões
A ação mais valiosa de um workflow comprometido é frequentemente a exfiltração de Secrets para um servidor controlado por um atacante. Restringir o acesso de rede de saída apenas aos domínios que seu workflow realmente precisa torna isso significativamente mais difícil. Harden-Runner e bullfrog funcionam em runners hospedados pelo GitHub. Para runners auto-hospedados, regras de firewall no nível da rede realizam a mesma coisa.
Se você usa GitHub Enterprise com runners auto-hospedados, allowlists de IP de token adicionam um controle na outra direção. Isso restringe quais IPs podem usar um token, assim, um token roubado não pode ser usado da infraestrutura de um atacante.
Permissões de token
27. Definir como predefinição GITHUB_TOKEN permissões somente leitura no nível da organização ou do repositório
O GITHUB_TOKEN está automaticamente disponível em cada execução de workflow. Por padrão, ele tem acesso extenso de leitura e escrita em todo o repositório, assim, qualquer workflow comprometido pode escrever em seu repositório, criar releases ou aprovar PRs. Defina o padrão para somente leitura em Configurações > Ações > Geral, então conceda permissões de escrita explicitamente apenas onde for necessário.
28. Declarar explicitamente permissions: blocos no nível do workflow ou da tarefa para restringir tarefas individuais
Definir um padrão somente leitura no nível da organização cria o padrão, mas algumas tarefas, é claro, precisam de mais permissões. Quando uma tarefa precisar de acesso elevado, declare um permissions: bloco no nível da tarefa em vez do nível do workflow. Dessa forma, o token elevado tem escopo apenas para aquela tarefa, e todas as outras tarefas no workflow permanecem somente leitura.
jobs:
deploy:
permissions:
contents: read
id-token: writeNa prática: Os ataques tj-actions, Trivy e prt-scan se beneficiaram de tokens com mais acesso do que o necessário. Restringir as permissões dos tokens reduz o raio de impacto geral.
Configurações da organização e do repositório
29. Desativar a possibilidade de as «Ações» aprovarem PRs
Por padrão, o GitHub permite que workflows aprovem pull requests usando o GITHUB_TOKEN. Isso significa que um workflow comprometido poderia aprovar suas próprias alterações maliciosas sem passar por nenhum processo de revisão. Desative isso em Configurações > Actions > Geral > "Permitir que o GitHub Actions crie e aprove pull requests." (Algumas equipes deixam isso ativado para o auto-merge do Dependabot, mas é melhor dar ao Dependabot uma conta de bot dedicada com permissões explícitas de revisor do que habilitar a aprovação de workflow para toda a organização.)
30. Restringir as fontes de ação a criadores verificados ou repositórios específicos
A configuração padrão no GitHub permite que qualquer action publicada no GitHub Marketplace seja usada em seus workflows. Restringir as fontes a criadores verificados ou a uma allowlist específica significa que uma action maliciosa recém-publicada não pode ser adotada em seus workflows sem aprovação explícita. Em vez disso, os desenvolvedores devem solicitar aprovação de quem gerencia as configurações da sua organização GitHub (geralmente a equipe de plataforma ou DevOps), que pode adicioná-la à allowlist. Configure isso em Configurações > Actions > Geral > "Permitir actions e workflows reutilizáveis."
Na prática: O comprometimento do tj-actions afetou 23.000 repositórios em parte porque as equipes não tinham restrição sobre quais actions poderiam incorporar.
31. Monitorize registos inesperados de runners auto-hospedados e repositórios públicos recém-criados na sua organização
Um token roubado permite que um invasor registre um runner malicioso para plantar um backdoor persistente. Invasores também criam rotineiramente repositórios públicos para despejar credenciais roubadas. Tanto o registro de runners quanto a criação de repositórios são eventos que sua equipe precisa ver imediatamente, mas o GitHub não os alerta por padrão. A solução alternativa é monitorá-los manualmente. Transmita o log de auditoria da sua organização para um SIEM e alerte sobre self_hosted_runners.register eventos e criação de repositórios. Sem um SIEM, você pode consultar o log de auditoria via API do GitHub ou verificar manualmente em Configurações > Audit Log.
Na prática: No ataque Shai-Hulud, máquinas comprometidas foram registradas como runners auto-hospedados chamados SHA1HULUD, e credenciais roubadas foram usadas para criar repositórios públicos utilizados como buckets de exfiltração. O monitoramento de ambos teria sinalizado a campanha precocemente.
32. Utilize CODEOWNERS para exigir uma revisão com critérios de segurança para alterações a .github/workflows/
Arquivos de workflow são códigos que são executados com acesso aos seus Secrets e tokens. Sem regras explícitas de propriedade, qualquer desenvolvedor com acesso de escrita ao repositório pode modificar um workflow e mesclá-lo sem revisão de segurança. Adicione uma entrada CODEOWNERS apontando .github/workflows/ para um revisor ou equipe que entenda as considerações de segurança, e combine-a com regras de proteção de branch que exijam a aprovação do CODEOWNERS antes da mesclagem.
33. Restringir ou desativar pull_request_target ao nível da organização ou do repositório, se não for necessário
As proteções de execução de fluxos de trabalho do GitHub permitem que os administradores impeçam que eventos específicos acionem fluxos de trabalho num repositório ou numa organização. Se nenhum dos seus repositórios precisar de pull_request_target, eliminar completamente o evento é melhor do que depender de que cada autor de fluxo de trabalho o utilize de forma segura. Configure esta opção nas definições de proteções de execução de fluxos de trabalho do seu repositório ou organização. Para os repositórios que realmente necessitem desta funcionalidade, as mesmas definições permitem restringir quais os intervenientes que podem acioná-lo.
Proteja os workflows do GitHub Actions com Aikido
Aikido detecta workflows inseguros do GitHub Actions e ajuda os desenvolvedores a corrigi-los antes que sejam explorados.
Ele detecta problemas como:
- Uso inseguro de
pull_request_target - Injeção de script através de não confiável
github.*input - Injeção de template e prompt em workflows com IA
- Actions de terceiros não fixadas
- Privilégios excessivos
GITHUB_TOKENpermissões - Manipulação arriscada de segredos em workflows
Aikido também pode:
- Criar PRs de correção automaticamente
- Detectar padrões de workflow inseguros em repositórios
- Sinalizar referências mutáveis do GitHub Action que devem ser fixadas a um SHA de commit completo
Aikido Safe Chain ajuda a proteger instalações de pacotes ao:
- Bloquear pacotes npm e PyPI maliciosos conhecidos
- Impor políticas de idade mínima para pacotes
Por exemplo, Aikido detecta entradas de usuário não sanitizadas em run: etapas e sugere automaticamente o padrão mais seguro de variável de ambiente.
Você está pronto para proteger os fluxos de trabalho do GitHub Actions
Mantenha esta lista de verificação à mão enquanto trabalha na proteção dos workflows do GitHub Actions. Tente configurar os itens que você pode fazer em apenas alguns minutos em breve, e compartilhe isso com seus colegas de equipe para que todos estejam cientes das mudanças.
FAQ: Segurança do GitHub Actions
Qual é a forma mais comum de exploração de workflows do GitHub Actions?
Injeção de script é o vetor mais frequente. Atacantes inserem código malicioso em nomes de branches, títulos de PRs ou corpos de issues, e workflows que interpolam esses valores diretamente em run: etapas os executam como comandos shell. Fixar ações em SHAs de commit e usar variáveis de ambiente em vez de interpolação inline fecha a maior parte dessa superfície.
O que é pull_request_target e por que é perigoso?
pull_request_target é um gatilho de workflow que é executado com acesso aos Secrets do repositório base, mesmo quando o PR que o aciona vem de um fork. Como qualquer pessoa pode abrir um PR contra um repositório público, qualquer workflow que use este gatilho expõe seus Secrets a contribuidores externos. Evite-o completamente em repositórios públicos.
O que significa "fixar ações em um commit SHA" e por que isso importa?
A maioria dos workflows referencia ações de terceiros por tag, como uses: some-action@v3. Tags são mutáveis, então, se a conta de um mantenedor de ação for comprometida, um atacante pode silenciosamente redirecionar essa tag para código malicioso. Fixar em um commit SHA completo como uses: some-action@abc123... significa que seu workflow executa apenas o que você revisou.
Devo usar runners auto-hospedados em repositórios públicos?
Não. Qualquer pessoa pode abrir um PR contra um repositório público e acionar um workflow. Em runners hospedados pelo GitHub, isso é gerenciável porque o ambiente é efêmero e isolado. Em um runner auto-hospedado, uma política de aprovação mal configurada significa que contribuidores externos podem executar código diretamente em sua infraestrutura.
O que é OIDC e por que é melhor do que armazenar credenciais da Cloud como Secrets?
Credenciais estáticas armazenadas como Secrets do GitHub são válidas indefinidamente, então um Secret roubado permanece perigoso muito tempo depois da violação. OIDC permite que seu workflow solicite um token de curta duração da AWS, Azure ou GCP, com escopo para aquele job específico, válido por minutos. Não há credenciais de longa duração para roubar.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "TechArticle",
"@id": "https://www.aikido.dev/blog/checklist-github-actions#article",
"headline": "The complete GitHub Actions security checklist",
"description": "GitHub Actions misconfigurations have been behind some of the biggest supply chain attacks of 2025 and 2026. This checklist covers the real attack vectors, what went wrong, and how to fix it.",
"url": "https://www.aikido.dev/blog/checklist-github-actions",
"datePublished": "2026-05-11",
"dateModified": "2026-05-11",
"inLanguage": "en-US",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://www.aikido.dev/blog/checklist-github-actions"
},
"author": {
"@type": "Person",
"@id": "https://www.aikido.dev/team-members/dania-durnas",
"name": "Dania Durnas",
"jobTitle": "Content Marketing",
"url": "https://www.aikido.dev/team-members/dania-durnas",
"worksFor": {
"@type": "Organization",
"name": "Aikido Security",
"url": "https://www.aikido.dev"
},
"sameAs": [
"https://www.linkedin.com/in/daniadurnas/"
]
},
"publisher": {
"@type": "Organization",
"name": "Aikido Security",
"url": "https://www.aikido.dev",
"logo": {
"@type": "ImageObject",
"url": "https://www.aikido.dev/logo.png"
}
},
"keywords": [
"GitHub Actions security",
"CI/CD security",
"supply chain attack",
"pull_request_target",
"script injection",
"mutable action references",
"tj-actions",
"workflow security",
"GitHub Actions checklist",
"DevSecOps",
"secrets management",
"self-hosted runners",
"OIDC",
"GITHUB_TOKEN",
"prt-scan",
"Trivy attack",
"Ultralytics attack",
"Safe Chain"
],
"about": [
{
"@type": "Thing",
"name": "GitHub Actions",
"url": "https://github.com/features/actions"
},
{
"@type": "Thing",
"name": "Supply Chain Security"
},
{
"@type": "Thing",
"name": "CI/CD Pipeline Security"
}
],
"mentions": [
{"@type": "SoftwareApplication", "name": "GitHub Actions"},
{"@type": "SoftwareApplication", "name": "Safe Chain", "url": "https://aikido.dev/safe-chain"},
{"@type": "SoftwareApplication", "name": "Aikido Security", "url": "https://www.aikido.dev"},
{"@type": "Thing", "name": "tj-actions supply chain attack"},
{"@type": "Thing", "name": "Trivy attack"},
{"@type": "Thing", "name": "Ultralytics attack"},
{"@type": "Thing", "name": "prt-scan campaign"},
{"@type": "Thing", "name": "CVE-2025-30066"}
],
"speakable": {
"@type": "SpeakableSpecification",
"cssSelector": ["h1", "h2", ".intro"]
},
"articleSection": [
"Trigger configuration",
"Handling untrusted input",
"Artifact handling",
"Mutable action references",
"Mutable package dependencies",
"Secrets handling",
"Runners",
"Token permissions",
"Org and repo settings"
],
"timeRequired": "PT15M"
},
{
"@type": "BreadcrumbList",
"@id": "https://www.aikido.dev/blog/checklist-github-actions#breadcrumb",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://www.aikido.dev"
},
{
"@type": "ListItem",
"position": 2,
"name": "Blog",
"item": "https://www.aikido.dev/blog"
},
{
"@type": "ListItem",
"position": 3,
"name": "The complete GitHub Actions security checklist",
"item": "https://www.aikido.dev/blog/checklist-github-actions"
}
]
},
{
"@type": "Organization",
"@id": "https://www.aikido.dev#organization",
"name": "Aikido Security",
"url": "https://www.aikido.dev",
"logo": {
"@type": "ImageObject",
"url": "https://www.aikido.dev/logo.png"
}
}
]
}
</script>

