
Varre código em busca de caracteres Unicode bidirecionais invisíveis (prevenção contra ataque Trojan Source, CVE-2021-42574)
Caracteres Unicode bidirecionais invisíveis podem fazer o código fonte ser exibido de forma diferente do que ele executa. Isso é o CVE-2021-42574 — o ataque Trojan Source.
Um atacante insere caracteres que invertem a direção do texto. Em uma revisão de código, você vê:
access_level = "admin"
Mas o compilador vê:
access_level = "user"
Os caracteres são invisíveis. Seu editor não os mostrará. Seu revisor não os perceberá. bidi-guard vai.
pip install bidi-guard
# Escaneia o diretório atual recursivamente
bidi-guard scan .
# Escaneia um arquivo específico
bidi-guard scan src/auth.py
Encontra todos os caracteres Unicode bidirecionais, mostra sua posição exata, contexto e gravidade.
name: BiDi Guard
on: [push, pull_request]
jobs:
bidi-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install bidi-guard
- run: bidi-guard ci .
Adicione ao seu .pre-commit-config.yaml:
repos:
- repo: https://github.com/Moshe-ship/bidi-guard
rev: v0.1.0
hooks:
- id: bidi-guard
Todos os 16 caracteres de controle bidirecional Unicode:
Caracteres marcados como Alta ou Crítica podem reordenar ativamente o texto exibido — estes são os usados em ataques Trojan Source.
from bidi_guard import scan_file, Finding
findings = scan_file("src/auth.py")
for f in findings:
print(f"{f.char_name} at line {f.line}:{f.col} — severity: {f.severity}")
Esses caracteres são invisíveis. Literalmente invisíveis:
grep "RLO" file.py # não encontra nada
cat file.py # parece completamente normal
bidi-guard mostra o que o grep não pode: o caractere exato, sua posição, contexto ao redor, nível de gravidade e o que ele faz. Também pode corrigir automaticamente removendo-os.
MIT — Musa, o Carpinteiro
Trazido a você pela Comunidade Saudita de IA — para os árabes primeiro, e o mundo em geral.
| Comando | O que faz |
|---|
scan | Escaneia arquivos em busca de caracteres bidi, mostra resultados com contexto |
ci | Modo CI — sai com código diferente de zero se caracteres perigosos forem encontrados |
fix | Remove todos os caracteres bidi dos arquivos (interativo por padrão) |
explain | Mostra o que cada caractere bidi faz com exemplos visuais |
init | Gera um arquivo de configuração .bidi-guard.yml para o seu projeto |
| Ponto de Código | Nome | Abreviação | Gravidade |
|---|
| U+200E | Marca da Esquerda para a Direita | LRM | Baixa |
| U+200F | Marca da Direita para a Esquerda | RLM | Baixa |
| U+061C | Marca de Letra Árabe | ALM | Baixa |
| U+200D | Juntador de Largura Zero | ZWJ | Baixa |
| U+200C | Não Juntador de Largura Zero | ZWNJ | Baixa |
| U+2066 | Isolador da Esquerda para a Direita | LRI | Média |
| U+2067 | Isolador da Direita para a Esquerda | RLI | Alta |
| U+2068 | Primeiro Isolador Forte | FSI | Alta |
| U+2069 | Isolador Direcional Pop | PDI | Média |
| U+202A | Incorporação da Esquerda para a Direita | LRE | Média |
| U+202B | Incorporação da Direita para a Esquerda | RLE | Alta |
| U+202C | Formatação Direcional Pop | Média | |
| U+202D | Sobrescrita da Esquerda para a Direita | LRO | Alta |
| U+202E | Sobrescrita da Direita para a Esquerda | RLO | Crítica |
| U+2028 | Separador de Linha | LS | Média |
| U+2029 | Separador de Parágrafo | PS | Média |