Aikido

Até mesmo a lista de gemas pode executar o código de outra pessoa

O npm tornou os scripts de instalação opcionais. Eis qual é a situação do RubyGems e como restringir as suas próprias instalações.

Escrito por
Hunter Schwartz

Se a tua equipa estiver a jogar gem install ou instalar o pacote, em portáteis ou em CI, este artigo é para ti. É o tipo de coisa que nunca te esperarias. Uma gem pode executar código no teu computador sem um script de instalação. Aqui está como verificar se existem quatro gems que extraem dados que encontrámos no RubyGems, desativar este comportamento com novas configurações e ver o que o Aikido sinaliza no teu feed.

TL;DR

  • A instalação de uma gem do Ruby pode executar o código dessa gem antes de a sua aplicação a carregar. Os scripts de compilação das extensões nativas são executados durante a instalação. Os plugins do RubyGems são executados no final de gem install e, mais uma vez, em cada pedra preciosa subsequente comando, até mesmo lista de gemas ou gem -v.
  • O npm já resolveu esta questão. A versão 12 do npm tornou os scripts de instalação opcionais, incluindo as compilações nativas. O RubyGems continua a executar compilações de extensões e plugins por predefinição.
  • As versões estáveis do RubyGems e do Bundler 4.0.x não permitem desativar nenhum destes comportamentos. As versões preliminares da versão 4.1 incluem opções para desativar estas funcionalidades, mas estas estão desativadas por predefinição, pelo que terá de as ativar manualmente
  • AikidoAs novas regras de deteção identificaram quatro gems no RubyGems, publicadas entre 2013 e 2015, que enviam o nome de utilizador do instalador, uma captura de ecrã do macOS ou um sinal para um servidor remoto. As gems em questão continuam a poder ser instaladas à data de 4 de novembro de 2026.
  • Para impedir que gems maliciosas conhecidas cheguem ao computador de um programador, utilize Aikido Device Protection. Verifica gem install e instalar o pacote no Ruby 3 e versões posteriores, em comparação com o Aikido Intel, e bloqueia malware conhecido antes de este afetar o sistema de ficheiros.
  • Se for cliente do Aikido , o Aikido assinala estas «joias» como um problema de malware no seu feed.
  • Em outubro, comunicámos à equipa de segurança do RubyGems a extensão, os caminhos de execução dos plugins e as quatro gems que identificámos como responsáveis pela exfiltração de dados. A equipa respondeu com perguntas sobre os indicadores de exclusão e não fez mais comentários.

Definições de exclusão

(Os indicadores e definições de exclusão aplicam-se apenas à versão 4.1.0.beta3):

  • Atualize o RubyGems e o Bundler para a versão 4.1.0.beta3.
  • Para gem install, passar --no-build-extension --no-install-plugin.
  • No Bundler, execute o comando `bundle config set` --global no_build_extension true e bundle config set --global no_install_plugin true.
  • No CI, defina BUNDLE_NO_BUILD_EXTENSION=true e BUNDLE_NO_INSTALL_PLUGIN=truee.

O que fazer se utilizar gems do Ruby

Se utilizar gems do Ruby, siga estes passos para garantir que o seu sistema está protegido. Caso contrário, pode ignorar esta secção para saber mais sobre o funcionamento destas funcionalidades.

1. Verifique se existem as quatro gemas maliciosas. Em cada projeto, procure todos os ficheiros de bloqueio no diretório atual:

grep -rE '^ +(xmastree|ancient-city-ruby|hacky|et_phone_home) \(' --include=Gemfile.lock .

Para verificar as gems instaladas sem executar um comando gem (o que carregaria os plugins), execute:

ruby -e 'Gem.path.each { |p| puts Dir.glob("#{p}/gems/*") }' | grep -E '/(xmastree|ancient-city-ruby|hacky|et_phone_home)-[0-9]'

Se utilizar o rbenv ou outro gestor de versões do Ruby, repita este procedimento para cada versão do Ruby. As versões afetadas constam da tabela do IOC no final deste artigo.

2. O que fazer se tiver instalado uma destas gems. A carga útil é executada a partir de um ficheiro Rakefile (extensão nativa) durante a instalação, pelo que bastou instalar a gem para que esta fosse executada.

  • Encerre todos os processos iniciados pela gem.
  • Desinstale a gem. Substitua GEM_NAME com o nome da gema em questão: gem uninstall GEM_NAME --all --executables
  • Remova a gem das dependências do seu projeto. Remova-a do seu Gemfile e, em seguida, execute instalar o pacote para regenerar o Gemfile.lock.
  • Avalie a exposição potencial. Analise as ações do gem na secção IOC para determinar o que poderá ter sido extraído e tome as medidas adequadas.

3. Verifique quais os plugins do RubyGems que tem instalados e desinstale os que não forem necessários. Execute o comando abaixo e anote cada diretório que for apresentado. O RubyGems carrega plugins de todos os caminhos de gems, não apenas do caminho predefinido.

ruby -e 'Gem.path.each { |p| puts Gem.plugindir(p) }'

4. Desative a compilação de extensões e a instalação de plugins sempre que possível. Para isso, é necessário ter o RubyGems e o Bundler 4.1.0.beta3. Instale-os com gem update --system 4.1.0.beta3, o que também atualiza o Bundler. (gem update --system --pre não o instala.)

  • Para gem install, passar --no-build-extension --no-install-plugin.
  • Para o Bundler, execute bundle config set --global no_build_extension true e bundle config set --global no_install_plugin true.
  • No CI, defina BUNDLE_NO_BUILD_EXTENSION=true e BUNDLE_NO_INSTALL_PLUGIN=true. Desative as compilações de extensões apenas numa tarefa de CI que não carregue a aplicação, como uma etapa de instalação de dependências ou de auditoria, a menos que todas as gems do seu pacote tenham uma compilação pré-compilada. Caso contrário, a sua aplicação e os seus testes não conseguirão carregar gems cujas extensões tenham sido ignoradas.

Estas definições apenas impedem a execução do código durante a instalação. O código de uma gem maliciosa continua a ser executado quando a sua aplicação ou os seus testes a carregam; por isso, estas definições protegem apenas as etapas específicas da instalação, e não tudo o que requeira o bundle.

5. É de esperar que as gems com extensões omitidas deixem de ser carregadas. O RubyGems não carrega uma gem cujas extensões declaradas não tenham sido compiladas, mesmo que o seu código nativo seja opcional, e apresenta a mensagem Ignoring <gem> because its extensions are not built. O Bundler considera que a gem está em falta, pelo que executar pacote falha com Could not find <gem> in locally installed gems, e todos os instalar o pacote reinstala-o.

As compilações pré-compiladas para plataformas não declaram extensões, pelo que continuam a ser carregadas. Depois de rever uma gem, restabeleça a sua extensão:

  • gem install: executar gem pristine <gem> --extensions. Isto também instala o plugin da gem, caso exista, e esse plugin é então executado. Para instalar apenas o plugin, execute gem pristine <gem> --only-plugins.
  • Bundler: não definido no_build_extension e executar instalar o pacote novamente. Continua no_install_plugin Defina esta opção se pretender que os plugins permaneçam desativados. Isto recompila todas as gems do pacote cujas extensões foram ignoradas. O próprio aviso do Bundler indica que se deve executar bundle pristine <gem>, mas na versão 4.1.0.beta3 isso falha com o mesmo erro Não foi possível encontrar erro, porque o Bundler não reconhece a gem como estando instalada. pacote intacto Funciona para uma gem em que apenas o plugin foi ignorado, embora também recompile a extensão.

6. Verifique as gemas novas ou atualizadas recentemente antes de as instalar. Num ambiente limpo, execute gem fetch e depois descompactar gem. Ler extconf.rb, mkrf_conf.rb, qualquer ficheiro Rakefile ou CMake listado em extensões no gemspec, e quaisquer lib/rubygems_plugin.rb.

Testámos estes comandos no Ruby 4.0.9 com o RubyGems e o Bundler 4.0.23 (a versão estável atual) e 4.1.0.beta3. Os parâmetros de exclusão, as definições e os passos de recuperação aplicam-se apenas à versão 4.1.0.beta3.

Duas formas como uma gem executa código no seu computador

O Ruby dispõe de duas formas de executar o código de uma gem sem nada que se assemelhe a um script de instalação: as Extensões Nativas e os Plug-ins do RubyGems. Ambas permitem que um atacante execute uma carga maliciosa antes de um programador iniciar a aplicação. Um script de compilação de extensão malicioso poderia roubar credenciais durante a instalação. Um plug-in malicioso do RubyGems poderia fazer o mesmo no final dessa mesma gem install, e novamente sempre que o programador executar um comando gem.

Método 1: Extensões nativas

Uma joia afirma extensões no seu gemspec (o manifesto da gem). Se um desses for um extconf.rb No script de compilação, o RubyGems executa esse ficheiro Ruby durante a instalação e, em seguida, executa o Makefile que este gera. O código Ruby contido nesse ficheiro é executado durante a instalação, da mesma forma que o node-gyp executa compilações nativas para pacotes npm.

O RubyGems também funciona mkrf_conf.rb como um script Ruby durante a instalação, caso uma gem indique um em extensões, e depois executa ancinho no mesmo diretório. Para além destes scripts Ruby, o RubyGems suporta compilações com o `configure`, o `Rakefile`, o CMake e o Cargo, sendo que cada um deles executa o código através da sua própria ferramenta de compilação.

O que um atacante acrescenta a uma gema:

  • Um ficheiro, extconf.rb ou mkrf_conf.rb (por exemplo, ext/foo/extconf.rb), contendo o código Ruby que quiserem
  • Uma linha no gemspec: spec.extensions = ["ext/foo/extconf.rb"]

Por que é fácil deixar escapar: Muitas ferramentas excelentes e legítimas, como o bcrypt e o bootsnap, utilizam extconf.rb. Parece um ficheiro de compilação como qualquer outro e não há uma secção separada de «scripts» que chame a atenção de quem revê o código.

Método 2: Plug-ins do RubyGems

Se uma gem incluir um ficheiro com o nome rubygems_plugin.rb, o RubyGems instala-o como um plugin. No momento da instalação, o RubyGems cria um pequeno carregador para esse ficheiro no seu diretório de plugins, e cada comando gem executado posteriormente carrega o conteúdo desse diretório.

O que um atacante acrescenta a uma gem: um ficheiro com o nome exato de rubygems_plugin.rb na raiz de um caminho «require» declarado, normalmente lib/rubygems_plugin.rb.

Quando estiver em funcionamento:

  • O RubyGems carrega um plugin recém-instalado imediatamente no final de gem install (se não estiver instalada nenhuma outra versão).
  • Posteriormente, carrega todos os plugins instalados sempre que for executado um comando `gem`, incluindo comandos apenas de leitura, como lista de gemas, pesquisa de gemas, e gem -v, bem como comandos relativos a gemas não relacionadas.
  • O plugin é executado repetidamente a cada comando, enquanto a gem permanecer instalada.

Por que é fácil deixar passar: É um ficheiro em lib/ com um nome específico. Não é necessária nenhuma declaração separada do plugin, pelo que um revisor que procure por ganchos de execução explícitos pode não o detetar. O RubyGems reporta as exceções relacionadas com o carregamento de plugins como avisos, pelo que o comando continua a ser executado mesmo que um plugin falhe.

Gems que o Bundler instala em fornecedor/pacote ou uma personalização BUNDLE_PATH funcionam de forma um pouco diferente. Um simples lista de gemas não carrega os seus plug-ins, mas bundle exec gem list sim.

O npm já passou por isto

A npm aprendeu da maneira mais difícil que a segurança na fase de instalação tem de abranger mais do que apenas os scripts do ciclo de vida. Na campanha «Miasma», os atacantes alteraram o seu gatilho de execução de package.json para binding.gyp, o ficheiro de compilação nativo do npm, que node-gyp é executado automaticamente durante a instalação. Verifica se apenas os ficheiros adicionados à lista de acompanhamento package.json A instalação dos hooks não foi efetuada. O npm 12 respondeu tornando opcionais os scripts de instalação de dependências, incluindo as compilações do node-gyp. 

O Ruby tem o mesmo problema e não dispomos de uma versão estável que o resolva. Um ficheiro extconf.rb parece uma configuração de compilação normal e um rubygems_plugin.rb não requer qualquer declaração, pelo que nenhum deles se assemelha a um script de instalação que deva ser revisto. Os atacantes já estão também a visar os programadores de Ruby. Na campanha SleeperGem, os atacantes publicaram versões maliciosas de gems a partir do que parecem ser contas de mantenedores inativas que foram comprometidas.

Um exemplo recente mostra que este caminho de execução está a ser utilizado para distribuir malware. Tanto Oliver Smith, da equipa de investigação do site Aikido, como Socket relataram o caso da versão 1.0.1 do strutil-core. O seu ficheiro extconf.rb descarregou o runtime do Bun e lançou uma carga útil integrada destinada a roubar credenciais durante a instalação. O malware partilha componentes funcionalmente idênticos com descendentes do Shai-Hulud anteriormente documentados, embora o código partilhado não permita determinar quem esteve por trás do mesmo. A RubyGems removeu ambas as versões publicadas a 1 de novembro. Este caso é distinto da nossa divulgação de outubro, mas ilustra o mesmo caminho de execução de extensões nativas descrito acima.

1 em cada 13 gem's populares executa código durante a instalação

A 26 de outubro de 2026, selecionámos as cerca de 1 000 gems mais populares, com base no total de downloads, a partir do site bestgems.org e analisámos as especificações publicadas dessas gems para compreender até que ponto as extensões nativas e os ficheiros de plug-in são comuns atualmente. É importante ter em conta que o facto de as gems utilizarem ou não estes mecanismos de instalação não constitui, por si só, um indicador de risco, uma vez que os atacantes podem recorrer a eles a qualquer momento. No entanto, isto demonstra até que ponto estas etapas de compilação parecem normais aos olhos de um revisor.

  • Extensões nativas: 74 de 997 (cerca de 1 em cada 13) declaram etapas de compilação de extensões, incluindo bcrypt, bigdecimal, bootsnap, bson, debug e muitas gemas comuns relacionadas com bases de dados e análise sintática.
  • Ficheiros de plugins: 2 de 997 (rdoc e yard) incluídos rubygems_plugin.rb. Ambos são carregados em comandos gem posteriores quando instalados no ambiente ativo.

Ainda é possível instalar quatro programas de demonstração que enviam dados para o servidor central

Ao testarmos as nossas regras de deteção, descobrimos quatro «joias», publicadas entre 2013 e 2015, que executam código durante a instalação: xmastree, ancient-city-ruby, hacky e et_phone_home. Estas aplicam enviam o nome de utilizador do instalador, uma captura de ecrã silenciosa do macOS ou um simples sinal para um servidor remoto.

Parecem ser provas de conceito ou testes de investigação, mas, mesmo assim, são executados após a instalação e enviam dados para fora do computador. As versões afetadas e os destinos constam da tabela de IOC no final desta publicação.

Cronograma de divulgação das nossas conclusões

  • 27 de outubro de 2026: Comunicámos os caminhos de execução das extensões e dos plug-ins à equipa de segurança do RubyGems. Esta respondeu com perguntas sobre os indicadores de exclusão e não fez mais comentários.
  • 30 de outubro de 2026: Comunicámos as quatro gemas à equipa de segurança da RubyGems.
  • 4 de novembro de 2026: Os gems referidos continuam disponíveis no RubyGems.

Os RubyGems estáveis não têm botão para desligar

Podes pensar que basta passar os sinalizadores --sem-extensão-de-compilação e --não-instalar-plugin para o gem. No entanto, ambas estas opções só existem nas versões pré-lançamento da 4.1 e, mesmo na 4.1.0.beta3, ambos os comportamentos permanecem ativos, a menos que os desative. Na versão estável 4.0.x, gem install rejeita-as como uma opção inválida.

Caminho de instalaçãoControlos para a compilação de extensões e a instalação de plug-ins
gem install, versão estável 4.0.xNenhuma. As bandeiras não existem.
instalar o pacote, versão estável 4.0.xNenhuma. Essas definições não existem.
gem install, 4.1.0.beta3--sem-extensão-de-compilação e --não-instalar-plugin sinalizadores. Ambos os comportamentos permanecem ativos, a menos que os desative.
instalar o pacote, 4.1.0.beta3no_build_extension e no_install_plugin configurações em configuração do pacote. Ambos os comportamentos permanecem ativos, a menos que os configure.

Como a Aikido detecta isso

Se for utilizador do Aikido , verifique o seu feed central e filtre por problemas relacionados com malware. Quando uma gem maliciosa aparece num dos ficheiros de bloqueio dos seus repositórios, Aikido assinala-a como um problema de malware. Aikido realiza uma nova verificação todas as noites, mas recomendamos que inicie uma nova verificação manual imediatamente se achar que pode ter sido afetado.

Para impedir que gems maliciosas conhecidas cheguem ao computador de um programador, utilize a Proteção de Dispositivos dAikido . Esta funcionalidade verifica os comandos «gem install» e «bundle install» no Ruby 3 e versões posteriores, comparando-os com a lista de gemas maliciosas da Intel ( Aikido ), e bloqueia o malware conhecido antes que este chegue ao sistema de ficheiros. Pode implementá-la através da sua ferramenta de gestão de dispositivos móveis (MDM).

IOCs para as quatro joias que apresentámos.

GemaVersãoAssinalado por AikidoO que faz
árvore de Natal0.0.2SimFicheiro Rakefile em extensões. Publicações whoami enviar para http://cryptic-ocean-8847.herokuapp.com/usernames durante a instalação.
árvore de Natal0.0.1SimA mesma carga útil e o mesmo URL, mas extensões está vazio, pelo que não é executado durante a instalação. Só é executado se alguém o executar ancinho dentro do diretório «gem».
cidade-antiga-rubi2013.1SimFicheiro Rakefile em extensões. Publicações whoami enviar para http://stark-samurai-8122.herokuapp.com/logs, e depois apaga-se a si próprio.
amador0.0.2 (única versão)SimFicheiro Rakefile em extensões. Tira uma captura de ecrã silenciosa e carrega-a para http://appfolio.herokuapp.com/upload Durante a instalação, apaga a captura de ecrã e, em seguida, apaga-se a si próprio. Só funciona no macOS.
et_phone_home0.1.0 (única versão)SimFicheiro Rakefile em extensões. Envia um pedido GET para http://176.31.142.25/ruby_no_way_you_got_here_randomly durante a instalação.
Compartilhar:

https://www.aikido.dev/blog/gem-list-runs-someone-elses-code

Verificar por malware

Comece Gratuitamente
4.7/5
Cansado de falsos positivos?

Experimente Aikido como 100 mil outros.
Começar Agora
Obtenha um tour personalizado

Confiado por mais de 100 mil equipes

Agende Agora
Escaneie seu aplicativo em busca de IDORs e caminhos de ataque reais

Confiado por mais de 100 mil equipes

Iniciar Escaneamento
Veja como o pentest de IA testa seu aplicativo

Confiado por mais de 100 mil equipes

Iniciar Testes

Torne-se seguro hoje,
de forma rápida e gratuita.

Proteja o seu código, a cloud e o runtime num sistema central.
Conecte um repositório para descobrir o que os agentes de raciocínio encontram na sua base de código.

Não é necessário cartão de crédito | Resultados do teste em 32 segundos.
Confiado por mais de 150 mil orgs