
Escanea código en busca de caracteres Unicode bidireccionales invisibles (prevención de ataques Trojan Source, CVE-2021-42574)
Los caracteres Unicode bidireccionales invisibles pueden hacer que el código fuente se muestre de forma distinta a como se ejecuta. Esto es CVE-2021-42574 — el ataque Trojan Source.
Un atacante incrusta caracteres que invierten la dirección del texto. En una revisión de código, ves:
access_level = "admin"
Pero el compilador ve:
access_level = "user"
Los caracteres son invisibles. Tu editor no los mostrará. Tu revisor no los detectará. bidi-guard sí lo hará.
pip install bidi-guard
# Scan current directory recursively
bidi-guard scan .
# Scan a specific file
bidi-guard scan src/auth.py
Encuentra todos los caracteres Unicode bidireccionales, muestra su posición exacta, contexto y severidad.
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 .
Añade a tu .pre-commit-config.yaml:
repos:
- repo: https://github.com/Moshe-ship/bidi-guard
rev: v0.1.0
hooks:
- id: bidi-guard
Los 16 caracteres de control Unicode bidireccionales:
Los caracteres con severidad Alta o Crítica pueden reordenar activamente el texto mostrado: estos son los que se utilizan en los 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}")
Estos caracteres son invisibles. Literalmente invisibles:
grep "RLO" file.py # finds nothing
cat file.py # looks completely normal
bidi-guard te muestra lo que grep no puede: el carácter exacto, su posición, el contexto circundante, el nivel de severidad y qué hace. También puede corregir automáticamente eliminándolos.
MIT — Musa the Carpenter
Presentado por la Comunidad de IA de Arabia Saudita — para los árabes primero, y para el mundo en general.
| Comando | Qué hace |
|---|
scan | Escanea archivos en busca de caracteres bidi y muestra los hallazgos con contexto |
ci | Modo CI — sale con código distinto de cero si se encuentra algún carácter peligroso |
fix | Elimina todos los caracteres bidi de los archivos (interactivo por defecto) |
explain | Muestra qué hace cada carácter bidi con ejemplos visuales |
init | Genera un archivo de configuración .bidi-guard.yml para tu proyecto |
| Punto de Código | Nombre | Abreviatura | Severidad |
|---|
| U+200E | Marca de Izquierda a Derecha | LRM | Baja |
| U+200F | Marca de Derecha a Izquierda | RLM | Baja |
| U+061C | Marca de Letra Árabe | ALM | Baja |
| U+200D | Conector de Ancho Cero | ZWJ | Baja |
| U+200C | No Conector de Ancho Cero | ZWNJ | Baja |
| U+2066 | Aislamiento de Izquierda a Derecha | LRI | Media |
| U+2067 | Aislamiento de Derecha a Izquierda | RLI | Alta |
| U+2068 | Aislamiento Fuerte Inicial | FSI | Alta |
| U+2069 | Aislamiento Direccional de Cierre | PDI | Media |
| U+202A | Incrustación de Izquierda a Derecha | LRE | Media |
| U+202B | Incrustación de Derecha a Izquierda | RLE | Alta |
| U+202C | Formato Direccional de Cierre | Media | |
| U+202D | Anulación de Izquierda a Derecha | LRO | Alta |
| U+202E | Anulación de Derecha a Izquierda | RLO | Crítica |
| U+2028 | Separador de Línea | LS | Media |
| U+2029 | Separador de Párrafo | PS | Media |