Hack de US$ 5,6 bi na Binance: a lição de segurança no Bun
Uma carteira apareceu no Arkham com o rótulo "Binance-hacker-1029" e um número que assusta: US$ 5,6 bilhões atribuídos a um hack da Binance. Abri a página da entidade no Arkham Explorer e fiquei um tempo olhando aquele valor. Este texto não vai bancar o perito em blockchain. Quero falar do que esse tipo de caso ensina para quem escreve backend, e no meu caso isso quer dizer Bun.
O que se sabe sobre o hack da Binance até agora
Vou ser honesto com você. O que existe de concreto é um rótulo público num explorador on-chain. O Arkham agrupa endereços em "entidades" e dá nome a elas. Neste caso o nome diz que é um hacker e que o dinheiro saiu da Binance.
Ainda não vi um relatório técnico confirmado explicando como aconteceu. Também não sei se os US$ 5,6 bilhões são o valor na hora do roubo ou o valor atual dos ativos. No mundo cripto essa diferença costuma ser enorme. Então trate o número como aproximado até sair um post-mortem oficial.
Mesmo assim, dá para tirar lição. A maioria dos grandes roubos em exchanges cai em poucas categorias:
- chave privada de hot wallet vazada ou mal guardada;
- máquina de um funcionário comprometida;
- dependência maliciosa na cadeia de build;
- falta de alerta para saída anormal de fundos.
Nenhuma delas exige um zero-day genial. Quase sempre o atacante só aproveita uma porta que ficou aberta.
Por que um dev de Bun deveria se importar
Talvez você esteja pensando: "eu não tenho uma exchange, faço API de agendamento". Justo. Só que o padrão de ataque é o mesmo, e só o tamanho do prejuízo muda.
Seu projeto tem uma chave de Stripe. Tem um token de acesso ao banco. Tem uma service account da AWS ou da Vercel. Se alguém pega isso, o estrago acontece em minutos, igualzinho.
E o JavaScript tem um problema histórico aqui. Qualquer pacote do npm pode rodar código na sua máquina durante a instalação. Nos últimos anos teve pacote popular sequestrado para roubar exatamente variáveis de ambiente e chaves de carteira.
Atacante não arromba o cofre. Ele procura a chave que alguém esqueceu na porta.
O que o Bun já faz por você na instalação
Aqui o Bun tem uma vantagem real, e uso isso como argumento quando alguém pergunta por que migrei.
O bun install não roda scripts de ciclo de vida (postinstall e companhia) das dependências por padrão. Só roda para pacotes que você liberou explicitamente em trustedDependencies no package.json:
{
"trustedDependencies": ["esbuild", "sharp"]
}
Isso fecha a porta mais usada em ataque de supply chain no ecossistema JS. Um pacote comprometido lá no fundo da sua árvore não consegue executar nada só por ter sido instalado.
Duas coisas que vale colocar no CI hoje:
bun install --frozen-lockfile
bun audit
O --frozen-lockfile faz o build falhar se o lockfile não bater com o package.json. Ninguém troca versão de dependência escondido. O bun audit confere seus pacotes contra a base de vulnerabilidades conhecidas.
Não é bala de prata. Um pacote malicioso ainda pode atacar quando é importado em runtime. Mas você tira de jogo o caso mais comum e mais barato para o atacante.
Como guardar segredos fora do .env
Esse é o ponto que mais me incomoda em projeto alheio. O .env vira um baú com tudo dentro, fica no disco em texto puro e um dia alguém comita sem querer.
Para desenvolvimento local, o Bun 1.3 trouxe o Bun.secrets, que usa o cofre do sistema operacional (Keychain no macOS, libsecret no Linux, Credential Manager no Windows):
import { secrets } from "bun";
await secrets.set({
service: "meu-app",
name: "stripe-key",
value: "sk_test_...",
});
const stripeKey = await secrets.get({
service: "meu-app",
name: "stripe-key",
});
Na prática, a chave sai do arquivo que qualquer script consegue ler com cat. Para produção, continue usando o gerenciador da plataforma (variáveis da Vercel, Secrets Manager da AWS, Vault). A regra é simples: segredo de verdade não mora no repositório e não mora em arquivo solto.
Mais três hábitos que custam pouco:
- uma chave por ambiente e por serviço, nunca a mesma para tudo;
- permissão mínima: o token do worker de e-mail não precisa escrever no banco;
- rotação com data marcada no calendário, não "quando der".
Monitorar saída é tão importante quanto proteger entrada
Repara numa coisa. Na blockchain, todo mundo viu o dinheiro saindo. É por isso que o Arkham conseguiu rotular a carteira. O problema é que ver depois não devolve nada.
No seu sistema vale o mesmo raciocínio. Você precisa de um alarme que dispare quando algo sai do normal: muitos estornos, muitas exportações de dados, um usuário baixando a base inteira às três da manhã.
Um alerta simples em Bun resolve o básico. Algo assim, rodando como cron:
const LIMITE_POR_HORA = 50_000; // em centavos, ajuste ao seu negócio
const res = await fetch(`${Bun.env.API_INTERNA}/saques?ultima_hora=1`, {
headers: { Authorization: `Bearer ${Bun.env.TOKEN_LEITURA}` },
});
const saques: { valor: number }[] = await res.json();
const total = saques.reduce((soma, s) => soma + s.valor, 0);
if (total > LIMITE_POR_HORA) {
await fetch(Bun.env.SLACK_WEBHOOK!, {
method: "POST",
body: JSON.stringify({ text: `Saída anormal: ${total / 100} na última hora` }),
});
}
Detalhe importante: o token desse script é só de leitura. Se o monitor for comprometido, o atacante consegue ver os números e mais nada. E um alerta que avisa em 10 minutos vale mais que um dashboard lindo que ninguém abre.
Se o seu sistema mexe com dinheiro, dá para ir além e colocar um limite duro. Acima de certo valor, a operação fica pendente até um humano aprovar. Chato? Um pouco. Mas aprovar saque é bem mais barato que explicar para o cliente por que o dinheiro dele sumiu.
O que eu mudaria no seu projeto hoje
Se você tem 30 minutos livres hoje, faria nesta ordem:
- Rodar
bun audite ler o resultado de verdade. - Conferir o
trustedDependenciese tirar o que não precisa estar lá. - Colocar
--frozen-lockfileno pipeline. - Procurar segredo vazado no histórico do git (
git log -p | grep -i "sk_live"já assusta muita gente). - Criar um alerta, um só, para a operação mais sensível do seu sistema.
Nenhum desses passos depende de você trabalhar com cripto. Todos reduzem o prejuízo se um dia alguém entrar.
Minha opinião sobre o caso
Ainda falta o relatório oficial para saber o que aconteceu. Pode ser chave vazada, pode ser engenharia social, pode ser algo novo. Meu palpite é que vai ser uma coisa sem graça, porque quase sempre é.
O que me irrita nesse tipo de notícia é a reação de sempre: todo mundo comenta o tamanho do número e quase ninguém revisa o próprio projeto. Com uma chave de US$ 5,6 bilhões ou de 5 mil reais, o erro costuma ser o mesmo. A diferença é que o seu não vira manchete, só vira um fim de semana perdido.
O Bun ajuda com padrões mais seguros na instalação e com o Bun.secrets. Só que ferramenta nenhuma resolve chave colada num arquivo esquecido. Quem resolve é a sua disciplina. Se quiser ver como aplico isso em produção, dá uma olhada nos projetos que mantenho.
Resumo para o LinkedIn
US$ 5,6 bilhões saíram de uma exchange gigante, e aposto que o erro foi algo bem sem graça. Ainda não saiu relatório oficial sobre o hack na Binance. Mas quase todo roubo grande começa com uma chave vazada, uma dependência maliciosa ou a falta de um alerta. O seu projeto pode não ter bilhões, mas tem chave da Stripe, token do banco e acesso à AWS. O ataque é o mesmo. Muda só o tamanho do estrago. No Bun eu começo pelo básico: trustedDependencies enxuto, --frozen-lockfile no CI, bun audit e Bun.secrets para tirar a chave do .env. E um alerta só, na operação mais sensível. Ver o dinheiro saindo depois não traz nada de volta. Escrevi o passo a passo completo no blog. Se você tem 30 minutos hoje, vale revisar o seu projeto. #Bun #SegurançaDaInformação #JavaScript #Backend #DevSecOps