
Сканировать код на наличие невидимых двунаправленных символов Юникода (предотвращение атаки Trojan Source, CVE-2021-42574)
Невидимые двунаправленные символы Unicode могут заставить исходный код отображаться иначе, чем он выполняется. Это CVE-2021-42574 — атака Trojan Source.
Злоумышленник встраивает символы, которые меняют направление текста. При проверке кода вы видите:
access_level = "admin"
Но компилятор видит:
access_level = "user"
Символы невидимы. Ваш редактор их не покажет. Ваш рецензент их не заметит. bidi-guard заметит.
pip install bidi-guard
# Сканировать текущую директорию рекурсивно
bidi-guard scan .
# Сканировать конкретный файл
bidi-guard scan src/auth.py
Находит все двунаправленные символы Unicode, показывает их точное положение, контекст и уровень опасности.
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 .
Добавьте в ваш .pre-commit-config.yaml:
repos:
- repo: https://github.com/Moshe-ship/bidi-guard
rev: v0.1.0
hooks:
- id: bidi-guard
Все 16 управляющих двунаправленных символов Unicode:
Символы, отмеченные как Высокий или Критический, могут активно изменять порядок отображаемого текста — именно они используются в атаках 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}")
Эти символы невидимы. Буквально невидимы:
grep "RLO" file.py # ничего не находит
cat file.py # выглядит совершенно нормально
bidi-guard показывает то, что grep не может: точный символ, его положение, окружающий контекст, уровень опасности и то, что он делает. Он также может автоматически исправить, удалив их.
MIT — Musa the Carpenter
Представлено вам Саудовским AI-сообществом — в первую очередь для арабов и всего мира.
| Команда | Что делает |
|---|
scan | Сканировать файлы на наличие bidi-символов, показать результаты с контекстом |
ci | Режим CI — завершается с ненулевым кодом, если найдены опасные символы |
fix | Удалить все bidi-символы из файлов (по умолчанию интерактивно) |
explain | Показать, что делает каждый bidi-символ, с наглядными примерами |
init | Сгенерировать конфигурационный файл .bidi-guard.yml для вашего проекта |
| Кодовая точка | Название | Сокращение | Уровень опасности |
|---|
| U+200E | Метка слева направо | LRM | Низкий |
| U+200F | Метка справа налево | RLM | Низкий |
| U+061C | Метка арабской буквы | ALM | Низкий |
| U+200D | Соединитель нулевой ширины | ZWJ | Низкий |
| U+200C | Разделитель нулевой ширины | ZWNJ | Низкий |
| U+2066 | Изолятор слева направо | LRI | Средний |
| U+2067 | Изолятор справа налево | RLI | Высокий |
| U+2068 | Изолятор первого сильного | FSI | Высокий |
| U+2069 | Изолятор отмены направления | PDI | Средний |
| U+202A | Встраивание слева направо | LRE | Средний |
| U+202B | Встраивание справа налево | RLE | Высокий |
| U+202C | Форматирование отмены направления | Средний | |
| U+202D | Переопределение слева направо | LRO | Высокий |
| U+202E | Переопределение справа налево | RLO | Критический |
| U+2028 | Разделитель строк | LS | Средний |
| U+2029 | Разделитель абзацев | PS | Средний |