Prezado GitHub,
Então, é o seguinte: há um problema de segurança que já é um segredo aberto há algum tempo. As pessoas falam sobre isso em rastreadores de problemas. Ele aparece em divulgações de segurança. É discutido em tópicos do Slack que inevitavelmente terminam com "... mas precisaríamos do GitHub para realmente expor esses dados".
Estou a chamar a sua atenção para isso porque estou cansado de ver essa conversa terminar sempre da mesma maneira. A comunidade de segurança está apenas a pedir visibilidade dos dados que já possui. Sem isso, ficamos parados. Os registos de pacotes não podem alertar os utilizadores. As ferramentas de segurança não podem sinalizar referências suspeitas. Os invasores, por sua vez, entendem perfeitamente esse ponto cego. Eles já estão a explorá-lo, assim como Shai Hulud fez.
Estamos a aproximar-nos do período de festas. E gosto de pensar que me comportei muito bem este ano. O meu único desejo é que nos dê as ferramentas para proteger melhor o ecossistema. Espero que não seja pedir demais!
Qual é o problema?
Gerenciadores de pacotes como o seu próprio npm, juntamente com terceiros como Bun e PyPI, permitem que os desenvolvedores instalem um repositório GitHub diretamente como uma dependência. O seu próprio GitHub Actions depende dessa mesma primitiva.
npm install github:trusted-org/trusted-package#commit-sha
bun install github:trusted-org/trusted-package#commit-sha
pip install git+https://github.com/trusted-org/trusted-package#commit- utiliza: organização confiável/pacote confiável@commit-shaA maioria das pessoas olharia para isto e pensaria: «Onde está o problema de segurança? Estou literalmente a especificar o repositório exato.»
Sim. Eu pensei a mesma coisa.
Mas eis o que acontece: se esse commit SHA existir num fork do repositório, você irá extrair o código do fork. Não do repositório na sua URL. Do fork. Mas que raio?
Deixe isso assentar por um segundo. Eu espero... O URL diz organização confiável/pacote confiável. Mas se um invasor bifurcasse esse repositório, adicionasse um commit malicioso e fizesse com que você referenciasse o SHA desse commit, você acabaria de instalar o código dele. Não o código que você pensava. Não o repositório que você especificou. O código dele.
Por que isso acontece?
Isso acontece devido à "Rede Fork" do GitHub.
Provavelmente nunca ouviu falar disso. Funciona assim: quando faz um fork de um repositório, não obtém uma cópia totalmente independente. O seu fork junta-se a uma rede, partilhando o armazenamento de objetos git subjacente com o original e todos os outros forks. É assim que o GitHub lida com a escala. Eles não armazenam um milhão de cópias dos mesmos commits. Faz sentido.
É também por isso que este ataque funciona.
Os comandos acima acabam por atingir o GitHub's "Descarregar um arquivo do repositório (tar)" endpoint. Os documentos dizem o seguinte sobre o proprietário parâmetro:

Não há garantias de que o código pertença diretamente ao repositório, nem avisos sobre a possibilidade de ele ter sido extraído de um fork. Honestamente? Dada a arquitetura, esse comportamento faz sentido. O commit existe no gráfico partilhado. O GitHub o serve. Isso não é errado.
O que é um problema é que isso cria uma ambiguidade que ninguém mais consegue perceber. Você pede organização confiável. Você recebe o código do invasor. O GitHub atendeu ao seu pedido. Só que você não recebeu o que pensava estar a pedir. E nenhuma ferramenta fora do GitHub consegue perceber a diferença.
A assimetria
Olha, nós realmente apreciamos quando você adicionou aquele banner de aviso no GitHub.com. Ver um aviso para commits como esses? Isso é útil. Mostra que você sabe que esse é um problema que vale a pena ser destacado.

Mas eis o problema: os gestores de pacotes não consultam o seu site. Eles chamam a sua API. E a API não lhes dá nenhuma indicação de que algo incomum está a acontecer. Nenhuma bandeira, nenhum metadado, nada documentado. Portanto, o npm não pode alertar os utilizadores. O PyPI não pode alertar os utilizadores. O Bun não pode alertar os utilizadores. A informação existe. Você já a está a exibir no frontend. Mas o ecossistema não consegue aceder a ela.
Porque não?
Hora de ser rigoroso
Lembra-se daquele ponto final«Baixar um arquivo do repositório (tar)» de que falamos? No momento, ele é o elo mais fraco. Mas também é o lugar óbvio para corrigir isso.
Aqui está uma ideia: adicionar um rigoroso parâmetro. Quando definido, a solicitação falha se o commit existir apenas em um fork, e não no repositório real especificado. Os gerenciadores de pacotes optam por participar, todos os outros mantêm o comportamento atual, nada quebra.
Já está a fazer essa verificação no frontend para aquele banner de aviso. Basta dar à API a mesma capacidade. Claro que seria ideal se pudesse expor mais informações da rede fork na sua API em geral, mas isso pelo menos resolve o problema mais evidente.
Boas festas!
Não estou a escrever isto como uma reclamação. Estou a escrever porque todos concordamos em querer um ecossistema seguro e confiável. Já reconheceram o problema ao exibir o aviso no GitHub.com. Agora, faria toda a diferença expor esse mesmo sinal através da API para que o ecossistema possa agir de acordo.
Uma pequena melhoria da sua parte permitiria uma melhoria significativa em todo o ecossistema. Não é esse o melhor tipo de melhoria?
E como estamos na época festiva, quero partilhar algo que tenho ouvido nos bastidores. Nas últimas semanas, conversei com alguns dos maiores atores do ecossistema, e há uma preocupação silenciosa e comum de que algo possa correr mal enquanto todos tentam tirar uma folga para passar tempo com os seus entes queridos. Resolver esta questão não eliminará esse risco, é claro, mas a preocupação é real e amplamente sentida.
Boas festas, GitHub. Que o final do ano seja tranquilo.
Proteja seu software agora



.avif)
