· Allan Lancioni
Como identifiquei um golpe em “teste técnico”: análise real de um malware direcionado a desenvolvedores
O ataque não dependia de vulnerabilidade técnica, dependia de confiança.
Por que esse caso é importante#
Essa semana recebi uma oportunidade “imperdível” no LinkedIn: vaga sênior, salário em USD muito acima da média, remoto, flexível.
Troquei algumas palavras com suposto CEO da empresa, e então ele mandou o teste técnico.
Era só um projeto React.
Mas se eu tivesse rodado um npm start sem olhar o código, teria entregado chaves, dados pessoais, histórico do navegador e até dinheiro.
Nesse artigo faço a engenharia reversa de um golpe que recebi, explicando como funciona o ataque pelos vetores técnico e social, e mostrando como se prevenir.
1. Identificando o primeiro contato#
O golpe começa no LinkedIn.
O alvo costuma ser desenvolvedores experientes, especialmente quem já trabalhou com blockchain, criptomoedas ou devs JavaScript. São perfis de alto ROI para o atacante.
O “recrutador” se apresenta como CEO de um projeto novo. O perfil parece legítimo, a empresa também: site básico, descrição coerente, JD bem escrita e vaga pagando acima da média.
O fluxo é:
- ele pede seu CV e GitHub
- diz que você “passou na primeira etapa”
- afirma que a próxima etapa é uma entrevista técnica
- mas antes disso, te envia a codebase para “estudo”, supostamente para você se preparar para a entrevista
É aí que o ataque acontece.

Red flags: salário alto demais, buzzwords como blockchain/cripto, codebase antes de entrevista, urgência no processo, perfis e sites com sinais de simulação
2. O primeiro alerta: um script de start “inocente” demais#
Ao abrir o repositório, algo no package.json me chamou atenção:
"start": "npm run check-env && npm run app:pre | react-scripts start
Antes de iniciar o projeto React, dois scripts eram executados: check-env e app:pre.
Ao abrir o check-env, encontrei algo bem específico: o script bloqueava a execução em VSCode, GitPod e outros ambientes isolados.
Por que um projeto React impediria execução em ambiente isolado?
Isso é uma forma do código garantir execução no terminal real, com acesso ao Sistema Operacional.

3. Usando o Copilot como scanner de anomalias#
Não rodei o projeto.
Pedi ao Copilot para scanear o projeto em busca de potenciais ameaças.
Ele encontrou isto:

O arquivo frontController.js, executado em npm run app:pre, em ~15 linhas, tinha:
- um token grande que na verdade era uma URL ofuscada em Base64
- um uso perigoso de
new Function - uma chamada a
verify()que enviava dados para um servidor desconhecido
Comecei a investigar.
4. O ponto crítico: Remote Code Execution (RCE)#
Havia apenas um trecho de código suspeito no projeto, e ele estava disfarçado como "verificação de API".
Vamos analisar o código de ataque:

Esse bloco é o coração do ataque. As funções auxiliares ajudam a mascarar o fluxo:

O que realmente acontece aqui#
- ao iniciar o projeto, a função
validateApiKey()é executada - o "Token" é uma URL escondida em Base64
setApiKey()decodifica essa URLverify()envia uma requisição HTTP para esse servidor externo- o servidor responde com um script JavaScript completo
- o projeto executa esse script localmente via
new Function("require", response.data)
O new Function funciona como uma porta aberta no ambiente de execução: ele aceita uma string e transforma aquilo em código real. É o mesmo princípio do eval, só com outra sintaxe.
Se você rodar
new Functionvindo da internet, não é azar quando dá errado. É consequência.
Isso é Remote Code Execution (RCE). O atacante controla o que a sua máquina executa no momento em que você roda o projeto.
O repositório é só o “veículo”. O ataque real está no servidor.
5. Testando o endpoint em ambiente controlado#
Ao decodificar o Base64, encontrei a URL:
https://ip-api-test.vercel.app/api/ip-check-encrypted/3aeb34a31
Via GET, devolvia apenas o IP. Normal.
Mas via POST, replicando headers e variáveis do projeto, recebi exatamente o esperado:

Um payload de ~700k caracteres, totalmente ofuscado, ou seja, modificado para dificultar a leitura.

6. O que o script fazia de verdade#
Era malware. Um stealer voltado para cripto.
Reconstruindo trecho a trecho com LLMs, ficou claro o funcionamento:
- famílias de browsers separadas
- caminhos específicos por navegador
- lista de IDs de wallets (MetaMask, Binance, etc...)
- arquivos-alvo por wallet
- domínios de destino para envio

O alvo: roubar wallets e sessões armazenadas no navegador do desenvolvedor.
7. Conclusão#
O que mais chamou atenção nesse caso não foi o código malicioso em si, mas o contexto em que ele foi entregue.
O ataque não dependia de vulnerabilidade técnica, dependia de confiança.
Uma oferta boa demais, um “teste técnico”, um projeto aparentemente legítimo.
Uma única ação esperada: rodar o código.
Reflexos que vale desenvolver#
- Leia o que vai rodar. Especialmente
start,prestart,postinstall. - Código desconhecido só em ambiente isolado. Use sandbox: WSL, VM ou Docker.
- IA como scanner. Um Copilot ou LLM lendo o código com você pode ser bem útil.
- Repo falso deixa cheiro. Commits nonsense, autores novos, nada sendo realmente modificado...
