1 pontos por GN⁺ 2025-10-17 | 1 comentários | Compartilhar no WhatsApp
  • O pesquisador compartilha a experiência de ter descoberto uma vulnerabilidade no Nixpkgs que permitia injetar código malicioso em todo o ecossistema Nix
  • Explica o risco estrutural de o gatilho GitHub Actions pull_request_target expor permissões sensíveis e segredos mesmo em PRs de contribuidores externos
  • Demonstrou na prática que era possível escalar privilégios por meio de injeção de comandos e uso de links simbólicos em tarefas do editorconfig-checker e de validação de code owners
  • Assim que a falha foi descoberta, a equipe mantenedora do Nixpkgs corrigiu rapidamente a vulnerabilidade, desativou os workflows vulneráveis e revisou a operação das permissões
  • Reforça a importância de separar dados não confiáveis de operações sensíveis na infraestrutura de CI/CD, aplicar o princípio do menor privilégio e fortalecer políticas

Hackeando todo o ecossistema Nix

Introdução e contexto

  • No NixCon do ano passado, o pesquisador e sua colega Lexi apresentaram uma vulnerabilidade no Nixpkgs
  • A falha descoberta abria a possibilidade de inserir código malicioso em todo o ecossistema Nix por meio de um ataque à cadeia de suprimentos
  • Foi uma experiência de resposta rápida, da detecção da vulnerabilidade ao reporte e à contenção, tudo em apenas um dia
  • Como o pesquisador não poderá participar do NixCon este ano, detalha o processo neste texto

GitHub Actions: um alvo vulnerável

  • GitHub Actions é um sistema que oferece suporte a várias tarefas de automação (CI/CD) em repositórios de código
  • Basta ter acesso aos arquivos de workflow para que seja fácil inserir código, o que o torna um alvo importante de ataques à cadeia de suprimentos
  • Os arquivos de workflow são escritos em YAML e, como não foram pensados como um formato de execução, podem conter vulnerabilidades de segurança inesperadas
  • Como exemplo simples, há workflows que executam comandos quando código é enviado ao repositório

O perigoso gatilho pull_request_target

  • O GitHub Actions tem vários gatilhos, e pull_request_target é bem diferente do pull_request comum
  • Por padrão, o pull_request_target tem permissões de leitura/escrita e acesso a segredos mesmo vindos de forks (PRs)
  • Quando esse gatilho é usado de forma incorreta, dados externos não confiáveis acabam combinados com permissões sensíveis
  • A própria documentação oficial do GitHub alerta claramente para esse risco
  • O pesquisador analisou 14 workflows que usavam pull_request_target no repositório Nixpkgs

Vulnerabilidade no editorconfig-checker

  • O primeiro workflow vulnerável encontrado tinha como objetivo verificar regras do editorconfig
  • Depois de calcular a lista de arquivos alterados, ela era passada ao editorconfig-checker com xargs
  • Se o aviso de segurança do comando xargs for ignorado, surge uma vulnerabilidade que permite inserir nomes de arquivo maliciosamente projetados (por exemplo, --help)
  • Com isso, torna-se possível manipular o editorconfig-checker de forma arbitrária ou até abrir caminho para execução adicional de comandos (a análise detalhada ainda exige revisão)

Vulnerabilidade no codeowners-validator: inclusão de arquivo local

  • A segunda vulnerabilidade, mais grave, foi encontrada no workflow de validação do arquivo CODEOWNERS
  • Esse processo faz checkout do código da PR e depois usa o codeowners-validator para verificar o arquivo
  • Quem envia a PR pode substituir o arquivo OWNERS por um link simbólico, permitindo referenciar arquivos arbitrários no runner (por exemplo, credenciais da action)
  • Como resultado, durante a validação o conteúdo desse arquivo é impresso nos logs, o que expõe um token do GitHub com permissão de leitura/escrita
  • Com esse token em mãos, torna-se possível fazer push diretamente no repositório Nixpkgs

Medidas tomadas e lições aprendidas

  • Após o reporte da vulnerabilidade, o mantenedor do Nixpkgs infinisil reagiu imediatamente
    • Desativou temporariamente os workflows vulneráveis
    • Corrigiu e separou os pontos em que dados não confiáveis estavam ligados a permissões
    • Após a correção de segurança, alterou os nomes dos workflows para mitigar problemas de direcionamento por branch
  • Principais lições
    • Nunca combinar dados não confiáveis com segredos e operações sensíveis, ou no mínimo fazê-lo com extremo cuidado
    • Seguir o princípio de operação com menor privilégio
    • É essencial conhecer as diretrizes oficiais sobre permissões no GitHub Actions
  • Em caso de vulnerabilidades semelhantes, administradores da organização podem desativar o Actions em massa por política (há instruções de configuração)

Conclusão

  • Em apenas um dia, o pesquisador encontrou uma vulnerabilidade capaz de colocar todo o ecossistema Nix em risco, reportou o problema e participou da correção
  • Isso evidencia a necessidade de extremo cuidado ao usar o GitHub Actions, especialmente o pull_request_target
  • Ele agradece a Intrigus, da KITCTF, que ajudou na pesquisa, e a infinisil, que respondeu rapidamente
  • Leitores interessados são incentivados a consultar o vídeo da apresentação e materiais adicionais
  • No geral, o texto reforça a importância da segurança no GitHub Actions e as lições práticas aprendidas

1 comentários

 
GN⁺ 2025-10-17
Comentários no Hacker News
  • Acho que pull_request_target é fundamentalmente inseguro, e o GitHub deveria simplesmente remover esse recurso. Em geral se diz que, para usar pull_request_target com segurança, basta não executar durante o processo código controlado pela branch, mas na prática a superfície de ataque é muito maior por causa de injeção de argumentos, inclusão de arquivos locais e afins. Hoje, os únicos casos de uso legítimos são coisas como aplicar labels automaticamente ou postar comentários automáticos em PRs de terceiros. Não acho que esse tipo de tarefa precise, por padrão, de permissão de escrita no repositório. O GitHub deveria poder emitir um token limitado apenas a essa tarefa. Por isso eu marco no zizmor qualquer uso de gatilhos perigosos como pull_request_target; veja zizmor dangerous triggers

    • Também concordo, mas há um caso de uso quando a organização não permite forks. Algumas ferramentas fazem o merge fora do GitHub, e nesses casos surgem PRs com merge não limpo, o que impede o disparo do workflow pull_request. Nessa situação, pull_request_target é praticamente a única opção. Seria melhor se o GitHub criasse uma configuração para permitir workflows em PRs com merge não limpo, desativada por padrão e usada só para coisas como linters. Até lá, é uma pena que essa limitação nos force a usar apenas pull_request_target. E, por sinal, quando se usa esse tipo de ferramenta externa, fazer merge manual no GitHub quebra todo o fluxo; merge manual é terminantemente proibido
    • Em repositórios privados, usamos pull_request_target por dois motivos. Primeiro, porque o workflow sempre roda com base na main, então dá para bloquear código de teste não verificado. Segundo, porque no sub claim do JWT dentro do workflow o job_workflow_ref é fornecido de forma decisiva, o que permite controle de acesso granular em sistemas baseados em OIDC
    • Pela explicação do GitHub, pull_request_target roda no contexto base do PR, então impediria que código malicioso roubasse o repositório ou os secrets. Mas, na prática, quando você vê como é fácil vazar secrets, a situação fica até meio ridícula
    • Essa superfície de ataque já está sem solução há quase um ano. Vale lembrar do caso em que um pacote Python foi atingido por um nome de branch malicioso com código parecido com shellshock. Na época, houve também um blog organizando a variável vulnerável e o método de ataque sob a ótica de um pentester
  • Se a equipe do Nix tivesse adotado, como propus no RFC, builds reproduzíveis assinadas de forma independente de commits/reviews assinados, esse tipo de ataque de supply chain de última milha teria sido impossível. No fim, o NixPkgs quer ser fácil de editar por qualquer pessoa e tem medo de que tentativas focadas em segurança afastem voluntários; o objetivo é se concentrar numa distribuição hobby. Tudo bem, mas então isso precisa ser comunicado com clareza, e se quiserem proteger o que tem valor, deveriam parar de usar ou recomendar o Nix em ambientes críticos de segurança. Um sistema operacional que protege algo precisa exigir assinatura de hardware rigorosa por duas partes em toda mudança, e não pode depositar confiança em uma única máquina ou uma única pessoa. Foi por isso que criei o Stagex link do Stagex link do Codeberg

    • Primeiro, embora não seja uma posição oficial, quero comentar como contribuidor do nixpkgs que tenta melhorar a segurança. Imagino que o RFC mencionado seja o RFC 0100 "Sign Commits" (link). Como discutido no RFC, o maior obstáculo é a falta de suporte à assinatura de commits em dispositivos móveis. O nixpkgs não tem fôlego para se preocupar em desenvolver tooling móvel também. Eu defendo assinar commits e aumentar a provenance, mas hoje ainda é possível fazer push com commits não assinados ou com chaves não confiáveis. Em um projeto com foco em segurança como o Stagex, esse tipo de camada é obviamente necessário. Mas o nixpkgs segue uma filosofia de confiança diferente. Como não concordo com uma política de segurança a ponto de espantar voluntários, tenho curiosidade sobre estatísticas de quanto esse tipo de recurso realmente seria usado no nixpkgs. O nixpkgs não é apenas uma distro hobby; ele é bastante usado de verdade até por grandes empresas (basta olhar a lista de patrocinadores da NixCon 2025). Ativar mais recursos de segurança é algo positivo, e no futuro a situação pode mudar. Mas, neste momento, exigir assinatura de commits no nixpkgs me parece ter desvantagens grandes demais. Além disso, não lembro de ter visto no PR a parte de "independent signed reproducible builds", e, numa escala como a do nixpkgs, seria enorme para terceiros montar essa infraestrutura. Ainda assim, o NixOS está perseguindo builds quase totalmente reproduzíveis link do status, e chegou bem perto, mas ainda não a 100%. Em resumo, commits assinados ajudariam numa segurança melhor, mas para o nixpkgs também teriam um efeito negativo grande demais, então por enquanto é difícil. Fiquei curioso sobre o método de assinatura por hardware em duas partes do Stagex; seria legal se você explicasse. Por fim, reconheço a produtividade e o interesse do trabalho do Stagex, mas queria esclarecer alguns mal-entendidos
    • O Stagex é realmente impressionante, obrigado por compartilhar o link
    • Só queria deixar uma mensagem de apoio, é um projeto realmente interessante
    • Conheci o Stagex hoje pela primeira vez, e foi a descoberta mais interessante desta thread
    • Uau... é curioso ver que alguém já fez o que eu vinha querendo fazer há tanto tempo
  • Embora eu tenha passado a vida projetando sistemas computacionais, ainda fico muito espantado que workflows modernos continuem emitindo bearer tokens para programas em que confiam, até tokens de curta duração. Se o framework do GitHub Actions oferecesse apenas acesso a um socket Unix privilegiado ou a um ssh-agent, esse tipo de vulnerabilidade seria muito mais difícil de explorar

    • Concordo totalmente. Em vez de bearer tokens, deveríamos usar um esquema baseado em assinatura, e se a chave privada for exposta diretamente isso na prática não difere de um bearer token. Um signing agent faz esse papel. A API do GitHub é baseada em HTTP, mas só mutual TLS e um signing agent já bastariam
    • O padrão SPIFFE cumpre um papel parecido. Só que ninguém usa isso; acho que a indústria como um todo simplesmente não leva segurança realmente a sério
  • Ações de CI/CD para pull/merge requests são um verdadeiro pesadelo. Quando o desenvolvedor escreve etapas de teste ou validação, normalmente pensa em termos de “meu código roda no contexto da minha conta do GitHub/GitLab”. Isso vale para commits próprios ou de colegas do time, mas em PRs o pipeline de CI/CD executa código não confiável. É difícil manter essa diferença sempre clara. Para testes simples ou linters tudo bem, mas quando o trabalho precisa integrar com infraestrutura e exige mais permissões, rapidamente fica perigoso

    • O problema não é o CI/CD ser disparado por PR, e sim o GitHub ter dois gatilhos quase idênticos (pull_request e pull_request_target). Um deles (por exemplo, pull_request) é quase sempre seguro, a menos que seja usado incorretamente de propósito, enquanto o outro (pull_request_target) é quase impossível de usar com segurança. Pior ainda: o GitHub faz com que tarefas comuns como aplicar labels em PRs ou deixar comentários automáticos só sejam possíveis com o gatilho perigoso (pull_request_target), então todo mundo acaba sendo empurrado para uma escolha instável. As funcionalidades do GitHub Actions têm uma estrutura propensa a erro
  • Com o tempo, fico cada vez mais preocupado com ataques de supply chain. Não é só no sentido de “vou perder meu emprego por causa disso?” ou “surgiu um novo vetor de ataque em NixOS, CI/CD, Node etc.”, e sim uma preocupação mais filosófica. Quanto mais dependemos disso tudo, mais problemas inevitavelmente temos de lidar. Até coisas que deveriam ser tranquilas de usar já ficaram complicadas demais — VSCode, Emacs, Nix, Vim, Firefox, JS, Node, todos esses plugins e pacotes de dependência embolados. Então, por mais vergonhoso que seja, estou chegando cada vez mais perto da conclusão estranha de que só consigo sentir algum controle ou segurança usando papel e tecnologias mínimas, realmente simples. Sei que isso é irracional, mas estou cada vez mais saturado com essa complexidade. Já sinto até o limite da minha tolerância à complexidade

    • O próprio Emacs é seguro, e você pode auditar manualmente todas as extensões. Mas, se atualizar cegamente todas as extensões de forma automática como numa configuração do Nix, aí o problema aparece. Também dá para imaginar automação com LLM para detectar e filtrar exploits óbvios. A resposta correta para validação em escala corporativa seria verificar formalmente tudo com Coq, mas isso significaria jogar fora 99,999% do software existente
  • Se você olhar o aviso na man page do xargs, verá a frase “xargs cannot be used securely”. Mas esse problema de segurança é diferente do caso aplicado aqui. Neste caso, basta colocar -- no final para evitar o problema

  • A frase “xargs cannot be used securely” é frequentemente mal interpretada. Por exemplo, se você executar cat "$HOME/changed_files" | xargs -r editorconfig-checker --, esse problema específico mencionado aqui pode ser evitado

    • Mas isso é como bloquear XSS colocando manualmente <div>{escapeHtml(value)}</div> em cada valor de HTML. Se for preciso aplicar o uso seguro manualmente em todo lugar, então a abordagem já está errada desde o início
    • Embora esse aviso não se aplique exatamente a esta situação, o sentido semântico geral está correto. Nem todo programa oferece suporte a separadores de argumento como --, e a maioria dos usos de xargs é vulnerável a injeção de argumentos. Em outras palavras, executar comandos em geral é inerentemente perigoso. A culpa não é do xargs em si, e sim da realidade em que ferramentas são reutilizadas repetidamente em diferentes contextos de privilégio
  • O artigo tem uma falha crítica muito mais abrangente: no código do PR, o arquivo OWNERS pode ser trocado por um symlink, expondo qualquer arquivo arbitrário, como o arquivo de credenciais do GitHub Actions. Como o git permite commitar softlinks, praticamente qualquer workflow fica sujeito a esse risco

    • É verdade, mas, se bem me lembro, quando se executa pull_request_target as credenciais são do repositório de destino, ou seja, do repositório para o qual o merge seria feito. Se rodar em pull_request, as credenciais são do repositório de origem controlado pelo atacante
  • A única notícia “boa” é que OpenBSD e NetBSD ainda usam CVS para gerenciamento de pacotes, então não são afetados por essa vulnerabilidade. Não sei sobre o FreeBSD. Segurança, de certo modo, é obscuridade por falta de adoção. Dito isso, esses projetos também parecem estar pensando em migrar para git, e o OpenBSD provavelmente deve seguir com got(1)

    • É verdade, mas isso não é uma vulnerabilidade do git, e sim do GitHub Actions. Os BSDs estão indiretamente seguros porque o GitHub não suporta CVS. Se você usa git ou GitHub, mas não usa GitHub Actions, não é afetado
    • Não é um problema do git, e sim do GitHub, especificamente do GitHub Actions
    • Eles não recebem contribuições por e-mail? Nesse caso, podem até ficar mais expostos a ataques de personificação, não?