In this article
Como se defender do Glassworm: o malware invisível que está reescrevendo a segurança da cadeia de suprimentos
Em outubro de 2025, pesquisadores de segurança da Koi Security descobriram o Glassworm, o primeiro worm autorreplicante a atacar extensões do VS Code e usar caracteres Unicode invisíveis para ocultar código malicioso à vista de todos. Com mais de 35.800 instalações comprometidas e uma infraestrutura C2 ainda em operação, o Glassworm representa mais um avanço na evolução dos ataques à cadeia de suprimentos, que rompe com nosso modelo tradicional de segurança baseado em revisão de código.
Este artigo analisa o ataque Glassworm, traçando sua origem até a vulnerabilidade Trojan Source (CVE-2021-42574), e mostra como desenvolvedores e equipes de segurança podem detectar e impedir ataques com caracteres invisíveis usando o anti-trojan-source, uma ferramenta de detecção de código aberto para linha de comando que agora inclui análise Unicode por categoria e recursos aprimorados de geração de relatórios.
Principais conclusões:
Caracteres Unicode invisíveis podem ocultar código malicioso executável, literalmente invisível para quem revisa o código
A revisão tradicional de código, algumas visualizações de diff e o realce de sintaxe não conseguem detectar esses ataques
O ataque se propaga por meio de credenciais roubadas, transformando cada vítima em um novo vetor de infecção
A detecção exige ferramentas especializadas que analisem os caracteres Unicode por categoria, não apenas por listas explícitas
A evolução dos ataques com caracteres invisíveis
O artigo acadêmico apropriadamente chamado Trojan Source foi o ponto de partida. Porém, para sermos historicamente precisos sobre incidentes de segurança na computação, caracteres e glifos Unicode já haviam sido usados nas décadas anteriores para ocultar informações e confundir sistemas e usuários. Em sua essência, essa técnica não é nova.
Em novembro de 2021, os pesquisadores Nicholas Boucher e Ross Anderson, da Universidade de Cambridge, publicaram o artigo seminal Trojan Source: vulnerabilidades invisíveis, revelando uma vulnerabilidade crítica (CVE-2021-42574) que afeta praticamente todas as linguagens de programação modernas.
O problema central estava nos caracteres de controle bidirecional (bidi) do Unicode, capazes de reordenar visualmente o código-fonte de uma forma que engana quem o revisa, preservando a ordem lógica de execução seguida por compiladores e interpretadores.
Veja este código C:
bool isAdmin = false;
/*
begin admins only
*/ if (isAdmin) {
printf("You are an admin.\n");
/*
end admins only
*/ }O trecho acima parece protegido por uma verificação de acesso. No entanto, caracteres de controle Unicode ocultos podem fazer o comentário parecer código, alterando completamente o fluxo lógico. O compilador vê uma coisa; quem revisa o código vê outra.
Técnicas de ataque:
Retornos antecipados: fazem uma instrução `return` parecer estar dentro de um comentário
Transformação em comentário: fazem comentários parecerem visualmente código executável
Strings distorcidas: fazem literais de string parecerem visualmente código
Homóglifos: usam caracteres visualmente idênticos de escritas diferentes (CVE-2021-42694)
O efeito multiplicador na cadeia de suprimentos
Os pesquisadores do Trojan Source identificaram o efeito multiplicador crítico no desenvolvimento de software moderno:
"Se um invasor conseguir inserir vulnerabilidades direcionadas em código aberto enganando quem o revisa, é provável que softwares dependentes herdem essa vulnerabilidade."
É exatamente isso que estamos vendo acontecer em ataques reais hoje.
Glassworm: a próxima evolução (2025)
Quatro anos após a divulgação do Trojan Source, invasores estão usando essas técnicas em ataques reais. Em outubro de 2025, surgiu o Glassworm, o primeiro worm autorreplicante a usar caracteres Unicode invisíveis para comprometer extensões do VS Code no marketplace OpenVSX.
O que diferencia o Glassworm:
Injeção de código invisível: usa seletores de variação Unicode que geram zero saída visual. Não é ofuscado nem minificado: é literalmente invisível a olho nu
Autorreplicante: rouba credenciais do NPM, GitHub e OpenVSX para comprometer automaticamente outros pacotes e extensões, crescendo exponencialmente
Infraestrutura impossível de derrubar:
Blockchain Solana como C2 principal (imutável, não pode ser derrubada)
Google Calendar como C2 reserva (serviço legítimo que contorna controles de segurança)
Conexões diretas por IP com criptografia dinâmica
Recursos completos de RAT: transforma estações de trabalho de desenvolvedores infectadas em infraestrutura criminosa, com proxies SOCKS, servidores VNC ocultos e canais de comando P2P
Entenda o ataque Glassworm
Etapa 1: a carga maliciosa invisível
Ao examinar a extensão comprometida CodeJoy do VS Code (versão 1.8.3), pesquisadores de segurança encontraram o que pareciam ser linhas vazias entre as linhas 2 e 7:
import * as vscode from 'vscode';
// [MASSIVE GAP HERE - APPEARS EMPTY]
export function activate(context: vscode.ExtensionContext) {Mas aquele espaço não estava vazio. Ele continha código JavaScript executável codificado em caracteres Unicode não imprimíveis — especificamente, seletores de variação Unicode que não geram nenhuma representação visual.
Para quem desenvolve e revisa o código: linhas em branco ou espaços em branco.
Para ferramentas de análise estática: nada para analisar.
Para o interpretador JavaScript: código malicioso executável.
Etapa 2: C2 baseado em blockchain
O código invisível se conecta à blockchain Solana e lê os memos de transações de um endereço de carteira codificado. O que há dentro do memo? Um objeto JSON com um link codificado em base64 para baixar a próxima etapa:
{"link":"aHR0cDovLzIxNy42OS4zLjIxOC9xUUQlMkZKb2kzV0NXU2s4Z2dHSGlTdg=="}Decodificado: http://217.69.3.218/qQD%2FJoi3WCWSk8ggGHiSv%3D%3D
Observação: transações em blockchain são imutáveis e não podem ser excluídas nem alteradas. Carteiras de criptomoedas são pseudônimas; não há provedor de hospedagem ou registrador envolvido, e os invasores podem publicar novas transações com URLs de novas cargas maliciosas a um custo mínimo.
Etapa 3: coleta de credenciais
A carga baixada (criptografada com AES-256-CBC, com chaves transmitidas nos cabeçalhos da resposta HTTP) tem como alvo as seguintes credenciais confidenciais:
Tokens de autenticação do NPM — para publicar pacotes maliciosos
Tokens do GitHub — para comprometer repositórios
Credenciais do OpenVSX — para injetar mais extensões
Credenciais do Git — para enviar código malicioso
49 extensões de carteiras de criptomoedas diferentes — MetaMask, Phantom, Coinbase etc.
Mas há mais: um C2 reserva que usa o Google Calendar. O malware busca um evento do calendário cujo título contém um URL codificado em base64:
aHR0cDovLzIxNy42OS4zLjIxOC9nZXRfem9tYmlfcGF5bG9hZC9xUUQlMkZKb2kzV0NXU2s4Z2dHSGlUdg==Repare no caminho: /get_zombi_payload/ — sim, "zombi" como em botnet zumbi.
A próxima e última etapa se chama ZOMBI — o RAT completo (Remote Access Trojan). A carga final transforma as estações de trabalho de desenvolvedores infectadas em nós de uma rede de infraestrutura criminosa. Para isso, usa um proxy SOCKS para direcionar o tráfego dentro de redes corporativas, além de outros mecanismos de rede, como WebRTC, BitTorrent e VNC oculto.
O invasor pode usar seu navegador com as sessões em que você já está conectado, acessar seu e-mail e Slack, ler seu código-fonte, roubar outras credenciais e se movimentar para outros sistemas da sua rede — tudo isso sem que você veja nada acontecer na tela.
Detecte caracteres invisíveis com o anti-trojan-source
O projeto anti-trojan-source é uma ferramenta de segurança de código aberto criada especificamente para detectar ataques baseados em Unicode, incluindo injeções de caracteres invisíveis como as do Glassworm. Criada originalmente para detectar ataques Trojan Source, a ferramenta evoluiu para oferecer proteção abrangente, combinando a detecção de caracteres específicos com a análise Unicode por categoria.
O que o anti-trojan-source detecta
277 caracteres explicitamente identificados como confundíveis:
Controles bidirecionais Unicode (U+202A-U+202E, U+2066-U+2069)
Caracteres de largura zero (U+200B, U+200C, U+200D)
Seletores de variação (U+FE00-U+FE0F) — os 16 seletores básicos
Seletores de variação estendidos (U+E0100-U+E01EF) — 240 caracteres adicionais usados pelo Glassworm
Espaço sem quebra (U+00A0)
Juntor de palavras, hífen invisível e outros caracteres invisíveis
Detecção por categoria (preparada para o futuro):
Todos os caracteres de formatação Unicode (categoria Cf) — detecta caracteres de formatação invisíveis por categoria
Todos os caracteres de controle Unicode (categoria Cc) — exceto espaços em branco de uso comum (TAB, LF, CR)
Com essa abordagem baseada em categorias, o anti-trojan-source consegue detectar novos caracteres invisíveis adicionados ao Unicode no futuro, sem exigir atualizações explícitas à lista de caracteres.
Recursos de detecção
1. Detecção booleana simples
import { hasConfusables } from 'anti-trojan-source'
const code = readFileSync('suspicious-file.js', 'utf-8')
const isDangerous = hasConfusables({ sourceText: code })
if (isDangerous) {
console.error('⚠️ Invisible characters detected!')
}2. Resultados detalhados
import { hasConfusables } from 'anti-trojan-source'
const findings = hasConfusables({
sourceText: code,
detailed: true
})
findings.forEach(finding => {
console.log(`Line ${finding.line}:${finding.column}`)
console.log(` Character: ${finding.codePoint} ${finding.name}`)
console.log(` Category: ${finding.category}`)
console.log(` Context: ${finding.snippet}`)
})Exemplo de resultado:
Line 3:45
Character: U+E0100 VARIATION SELECTOR-17
Category: Variation Selector
Context: const value = getUserInput()
Line 12:8
Character: U+200B ZERO WIDTH SPACE
Category: Cf (Format)
Context: if (isAdmin) {3. Exemplo de uso da CLI com vários modos de saída
# Simple mode (exit code 1 if found)
npx anti-trojan-source --files='src/**/*.js'
# Verbose mode with detailed information
npx anti-trojan-source --files='src/**/*.js' --verbose
# JSON mode for programmatic processing
npx anti-trojan-source --files='src/**/*.js' --jsonGuia de implementação do anti-trojan-source
Instale a ferramenta de linha de comando no seu projeto:
1npm install -D anti-trojan-sourceOu use diretamente com npx (sem precisar instalar):
npx anti-trojan-source --files='**/*.js'Em seguida, analise um único arquivo:
npx anti-trojan-source src/index.jsOu analise vários arquivos usando padrões glob do shell:
npx anti-trojan-source --files='src/**/*.{js,ts,jsx,tsx}'A CLI do anti-trojan-source oferece o modo verbosemode para exibir detalhes. Ele é útil quando você precisa entender exatamente o que foi detectado e onde:
npx anti-trojan-source --files='src/**/*.js' --verboseExemplo de resultado:
[x] Detected cases of trojan source in the following files:
|
- src/utils.js
Line 12:34 - U+200B ZERO WIDTH SPACE [Cf (Format)]
Snippet: const value = getUserInput()
Line 45:10 - U+202E RIGHT-TO-LEFT OVERRIDE [Cf (Format)]
Snippet: if (isAdmin) { // Check permissions
Line 78:22 - U+E0100 VARIATION SELECTOR-17 [Variation Selector]
Snippet: const token = process.env.API_KEYTambém há suporte a um modo de saída JSON, que permite análises programáticas. Ele é útil para automação, integração com CI/CD e geração de relatórios personalizados:
npx anti-trojan-source --files='src/**/*.js' --jsonExemplo de resultado:
[
{
"file": "src/utils.js",
"findings": [
{
"line": 12,
"column": 34,
"codePoint": "U+200B",
"name": "ZERO WIDTH SPACE",
"category": "Cf (Format)",
"snippet": "const value = getUserInput()"
},
{
"line": 45,
"column": 10,
"codePoint": "U+202E",
"name": "RIGHT-TO-LEFT OVERRIDE",
"category": "Cf (Format)",
"snippet": "if (isAdmin) { // Check permissions"
}
]
}
]Integração com CI/CD
Veja a seguir um exemplo de como criar uma GitHub Action para incorporar ao seu processo de CI:
Crie o arquivo .github/workflows/security-scan.yml:
name: Unicode Security Scan
on:
pull_request:
push:
branches: [main, master, develop]
jobs:
scan-invisible-chars:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Scan for invisible Unicode attacks
run: npx anti-trojan-source --files='**/*.{js,ts,jsx,tsx,py,java,go,rs}' --json
- name: Fail on detection
if: failure()
run: |
echo "::error::Invisible Unicode characters detected in source code"
echo "::error::This could indicate a Trojan Source or Glassworm-style attack"
exit 1Detecção avançada por categoria
Entenda as categorias Unicode
O anti-trojan-source não procura apenas caracteres específicos: ele também analisa caracteres por categoria Unicode, preparando você para novos ataques.
Categoria de formatação (Cf):
Caracteres que afetam a formatação, mas não geram saída visual
Inclui controles bidirecionais, separadores invisíveis e caracteres de largura zero
Exemplos: U+200B (ESPAÇO DE LARGURA ZERO), U+202E (SUBSTITUIÇÃO DA DIREITA PARA A ESQUERDA)
Categoria de controle (Cc):
Caracteres de controle não imprimíveis
Intervalos: U+0000-U+001F e U+007F-U+009F
Exceção: TAB (U+0009), LF (U+000A) e CR (U+000D) estão em uma lista de permissões como caracteres legítimos
Por que a detecção por categoria é importante?
Uma abordagem tradicional seria semelhante ao seguinte código JavaScript:
const dangerousChars = ['\u200B', '\u200C', '\u200D', /* ... explicit list */];
// Problem: New Unicode versions add new characters
// Problem: Attackers can use unlisted charactersJá uma abordagem baseada em categorias se beneficiaria de:
Detecção de TODOS os caracteres de formatação (Cf), inclusive os que não estão listados explicitamente
Detecção de TODOS os caracteres de controle (Cc), exceto espaços em branco permitidos
Próximos passos
Não confie apenas na revisão visual do código, mesmo que algumas IDEs, como o VS Code e o visualizador de diff online do GitHub, já ofereçam algum suporte para indicar caracteres Unicode no texto. Não confie em algo só porque “parece certo” nem presuma que suas ferramentas exibem automaticamente caracteres invisíveis. Em vez disso, faça uma varredura proativa para detectá-los.
Recomendamos analisar todo o código antes de mesclar pull requests. Integre com o Snyk (é grátis) para executar análises estáticas de código automaticamente e monitorar continuamente seu projeto, com repositórios do GitHub e outras integrações.
Use o utilitário de linha de comando anti-trojan-source para detectar especificamente caracteres potencialmente perigosos no seu código-fonte.
Quer preparar seu pipeline de desenvolvimento para o futuro e se proteger contra a próxima evolução das ameaças à cadeia de suprimentos? Baixe o white paper: Como navegar pela cadeia de suprimentos de software moderna: protegendo o código aberto, o código gerado por IA e a conformidade com SBOM.
Recursos
Ferramentas:
CLI do anti-trojan-source: https://github.com/lirantal/anti-trojan-source
Plugin ESLint: https://github.com/lirantal/eslint-plugin-anti-trojan-source
Pesquisas:
Artigo Trojan Source: https://trojansource.codes/trojan-source.pdf
Análise do Glassworm: https://www.koi.ai/blog/glassworm-first-self-propagating-worm-using-invisible-code-hits-openvsx-marketplace
CVE-2021-42574: divulgação da vulnerabilidade Trojan Source
CVE-2021-42694: ataques com homóglifos
Padrões:
Padrão Unicode: https://unicode.org/standard/standard.html
Categorias Unicode: https://www.unicode.org/reports/tr44/#General_Category_Values
Proteja sua cadeia de suprimentos com a Snyk
87% dos entrevistados foram afetados por problemas de segurança na cadeia de suprimentos. Mantenha a sua protegida com a Snyk.