
Prova de conceito de exploração para CVE-2026-44590, uma injeção de comandos no fluxo de trabalho do GitHub Actions do Sherlock que permite RCE e exfiltração de GITHUB_TOKEN via pull_request_target.
Descoberto e reportado por: Astaruf
Artigo completo: https://nstsec.com/en/posts/sherlock-rce-pull-request-target-cve-2026-44590/
Aviso upstream: Aviso GHSA do sherlock-project/sherlock
Entrada NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-44590
Registro CVE: https://www.cve.org/CVERecord?id=CVE-2026-44590
Este repositório contém a prova de conceito para CVE-2026-44590, uma injeção de comandos no workflow validate_modified_targets.yml do GitHub Actions de sherlock-project/sherlock. Qualquer usuário do GitHub pode abrir um pull request que dispara a execução arbitrária de comandos no contexto privilegiado do CI, exfiltrar o GITHUB_TOKEN do workflow e auto-aprovar o PR malicioso, tudo sem qualquer interação humana.
Para o artigo técnico completo (análise de causa raiz, passo a passo da exploração, discussão de impacto e um capítulo sobre o que um atacante poderia fazer em cenários do mundo real), consulte o post do blog:
nstsec.com/en/posts/sherlock-rce-pull-request-target-cve-2026-44590
Este README foca exclusivamente no script PoC: o que ele faz, como executá-lo e o que esperar.
poc.pypoc.py é um único script Python autocontido (apenas stdlib) que automatiza toda a cadeia de ataque de ponta a ponta:
sherlock-project/sherlock se necessáriomaster do fork para o commit pré-correção para que o bug possa ser reproduzido mesmo após a correção upstreaminteractsh-client)GITHUB_TOKEN do callback OAST (no --mode exfil) e o decodifica em texto claroVULNERABILITY CONFIRMED ou FIX VERIFIEDinteractsh-client)Existe exatamente um passo manual necessário (clicar no banner "I understand my workflows" do GitHub na primeira vez por fork), porque não existe API pública para dispensá-lo. O script detecta esse caso e pausa com um prompt claro.
python3 poc.py --fork-owner <seu-usuario-do-github>
Faz fork do repositório (se necessário), sincroniza com o upstream (master corrigido), abre um PR malicioso, executa a cadeia de ataque e reporta FIX VERIFIED porque o workflow corrigido bloqueia o payload antes que qualquer comando shell seja executado.
python3 poc.py --fork-owner <seu-usuario-do-github> --vulnerable
Igual ao anterior, mas primeiro reverte o master do fork para o commit pré-correção (271608fb). Veredito esperado: VULNERABILITY CONFIRMED.
python3 poc.py --fork-owner <seu-usuario-do-github> --vulnerable --mode exfil
O payload de exfiltração despeja git config --list no OAST e dorme por 180 segundos para manter o workflow (e, portanto, o GITHUB_TOKEN) ativo. Enquanto o workflow está dormindo, o script extrai o token do log OAST, o decodifica e imediatamente chama a API do GitHub para aprovar o PR. O PR termina aprovado por github-actions[bot].
gh (GitHub CLI), autenticado:
gh auth login
gitinteractsh-client (opcional, mas recomendado). Quando instalado, o script o inicia automaticamente e verifica o callback dentro do próprio script:
go install github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest
Se preferir usar seu próprio endpoint OAST (Burp Collaborator, oast.fun via interface web, requestbin, etc.), passe-o com --oast-url e a etapa de verificação automática será ignorada.O script não exige que um fork exista previamente; ele cria um automaticamente.
--mode harmless (padrão)O payload é um único POST curl com uma string de confirmação estática. Nenhum segredo é lido, nenhuma chamada de API é feita; o único efeito colateral é o callback OAST. Use isso para confirmar que a vulnerabilidade existe sem expor nenhuma credencial.
--mode exfilO payload despeja git config --list (que contém o GITHUB_TOKEN codificado em base64 sob http.https://github.com/.extraheader) no OAST e depois dorme por 180 segundos. O script então:
x-access-token:ghs_XXXXXXXX....x-access-token: e usa o token bruto para chamar POST /repos/<fork>/pulls/<n>/reviews com o payload de aprovação padrão ({"event":"APPROVE","body":"All checks passed. LGTM!"}).github-actions[bot], indistinguível de automação legítima de CI.Uma vez registrada a aprovação, o script pula o restante do sono de 180 segundos do workflow, já que a cadeia de ataque está completa e esperar o runner expirar não acrescenta nada.
| Flag | Descrição |
|---|---|
--fork-owner <user> | Obrigatório. Usuário do GitHub que possui (ou possuirá) o fork |
--fork-name <name> | Nome do repositório do fork (padrão: sherlock) |
--oast-url <url> | Endpoint OAST que recebe o callback. Se omitido, o script inicia automaticamente o interactsh-client e executa o veredito dentro do script |
--mode harmless|exfil | Tipo de payload (padrão: harmless) |
--vulnerable | Força a redefinição do master do fork para o commit pré-correção (271608fb) antes de executar. Implica --no-sync |
--no-sync | Ignora a sincronização do fork com o upstream (útil ao testar um commit fixado) |
--base-branch <name> | Branch alvo do PR no fork (padrão: master) |
--keep-branch | Não exclui o branch do PoC após a conclusão |
--no-poll | Ignora a consulta de execuções do workflow e sai após a criação do PR |
Por design, o PoC abre o PR de um branch no fork para o master do mesmo fork. Ele não tem como alvo sherlock-project/sherlock diretamente. Há duas razões para isso.