montana/Android/Внешний-аудит/07-Известные-ограничения.md
2026-05-18 22:11:45 +03:00

11 KiB
Raw Blame History

07. Findings tracker — известные ограничения

Открытый реестр всех известных уязвимостей, дефектов и архитектурных gap. Severity по шкале:

  • блокер mainnet — запуск в production невозможен до закрытия
  • высокий — производственный риск, обязательно закрыть до публичного релиза
  • средний — допустимо запустить с явным acknowledgment
  • низкий — косметика, document-hygiene

Все findings имеют closure path — конкретные шаги для устранения.


Закрыто в v6.5.0 (Phase 1)

CF-1 — Swallowed catch без логирования

Класс: error surface (Pass 7). Severity: средний. Closure: commit cf1 (v6.5.0). 10/13 catch теперь логируют Log.w(TAG, ...). Остаётся 3 в Thread.sleep (interrupt handling, acceptable per Kotlin pattern).

CF-2 — Regex JSON parser

Класс: parser robustness (Pass 8/10). Severity: средний. Closure: commit cf2 (v6.5.0). Заменён на org.json.JSONObject с optDouble/optString/optBoolean и fail-safe NaN-проверкой.

CF-3 — BIP39 wordlist integrity check

Класс: integrity / supply chain (Pass 0 [C-9]). Severity: блокер mainnet до закрытия. Closure: commit cf3 (v6.5.0). Hardcoded SHA-256 2f5eed53...dbda в MainActivity.bip39(). Fail-closed: возвращает пустую строку → JS бросает «bip39 list size: 0» → создание кошелька невозможно.

CF-5 — balances.json race condition

Класс: concurrency (Pass 8). Severity: средний. Closure: commit cf5 (v6.5.0). Atomic with_state_lock() через отдельный .lock файл с единым LOCK_EX на read+modify+write.

CF-7 — silent JSON swallow на backend

Класс: error surface (Pass 7). Severity: низкий. Closure: commit cf7 (v6.5.0). force=True + явный 400 invalid json с detail.

F-1 — Stale assigned_node поле

Класс: consistency drift (Pass 13). Severity: низкий. Closure: commit f1 (v6.5.0). Удалены assigned_node/assigned_ts поля из всех записей balances.json.

F-3 (частично) — anon-bloat в balances.json

Класс: state lifecycle (Pass 18 / [I-14]). Severity: средний. Partial closure: commit f3 (v6.5.0). /api/vpn/admin/purge endpoint удаляет inactive 30+ days с balance=0. Manual trigger. Остаётся open: automated daily cron (см. ниже F-3.1).


Открытые findings

F-2 — Heartbeat без cryptographic authentication

Класс: authentication / Sybil (Pass 19, Pass 22). Severity: блокер mainnet.

Поверхность: POST /api/vpn/heartbeat принимает {"address": "<40-hex>"} и проверяет только request.remote_addr ∈ MONTANA_NODES. Никакой подписи владельца адреса не требуется.

Атака:

  1. Атакующий поднимает Montana VPN клиент (открытый VLESS link).
  2. Генерирует 10⁶ случайных 40-hex адресов.
  3. Шлёт 10⁶ heartbeat каждые 5 секунд через VPN.
  4. Backend начисляет 0.001 × 5 × 10⁶ = 5000 Ɉ/период на fake-адреса.

Defense сейчас: нет.

Closure path:

  1. Phase 3 (M-VPN-3): Falcon-512 keypair generation в Android — каждый кошелёк имеет (pubkey, secretkey) от seed.
  2. Heartbeat body расширяется: {address, window_index, exit_node, signature} где signature — Falcon-512 над (address || window_index || exit_node).
  3. Backend хранит pubkey per address (заполняется при первом heartbeat) → проверяет signature над всеми последующими.
  4. Atomic operation: верификация подписи → начисление credit.

Cost estimate: 2 недели (JNI bridge для pqcrypto-falcon + key derivation от BIP39 seed + backend signature verify).


F-4 — balances.json НЕ реплицируется на узлы Montana

Класс: persistence / SPOF. Severity: блокер mainnet.

Поверхность: balance state живёт только в /var/lib/montana-vpn-balance/balances.json на Moscow. Если Moscow упадёт безвозвратно (диск, hosting termination, государственный захват) — все начисленные Ɉ потеряны.

Что я ошибочно заявлял раньше: «всё сохраняется на узлах через montana-orchestrator.service». Неверно — orchestrator занимается регистрацией узлов, не балансами.

Closure path:

  1. Phase 2 (M-VPN-1): реплицировать balances.json на Helsinki + Frankfurt + NewYork через rsync daily. Mitigation, не fix.
  2. Phase 3 (M-VPN-2): интегрировать с TimeChain — heartbeat становится подписанной операцией 0x06 VpnHeartbeat → попадает в proposal → cemented через консенсус → AccountTable обновляется на ВСЕХ узлах. Authoritative persistence.

Cost estimate: Phase 2 — 3 дня. Phase 3 — 2 недели (новый opcode в спеке + mt-account изменения + montana-node integration).


F-6 — Seed в plain text без шифрования

Класс: privacy at rest (Pass 19). Severity: высокий (на rooted устройствах).

Поверхность: localStorage.setItem("m.seed", "ranch basket resource ...") в WebView Local Storage leveldb.

Атаки:

  • Root доступ к /data/data/quest.montana.vpn/app_webview/Default/Local Storage/leveldb/ → читает плоский текст
  • Forensic image устройства → offline analysis
  • Backup через ADB → seed в backup

Closure path:

  • User passcode + PBKDF2(passcode → AES key) → wrap seed AES-GCM
  • Или Android Keystore (hardware-backed) для wrap

Cost estimate: 1 неделя (UX flow + crypto + миграция existing wallets).


F-7 — Backup confirmation отсутствует

Класс: UX-as-security. Severity: высокий (вероятная потеря денег пользователями).

Поверхность: см. 06-Восстановление.md §6.

Closure path: новый экран s-backup-verify между s-auth и s-main при создании.

Cost estimate: 1 день.


F-8 — BIP44 несовместимость для cross-wallet import

Класс: narrative-model divergence. Severity: средний (UX).

Поверхность: см. 06-Восстановление.md §5. 24 слова Montana → импорт в Trust/MetaMask показывает пустые балансы.

Closure path (выбор):

  • A. Добавить UI warning при показе seed
  • B. Apply for SLIP-44 coin type + переход на BIP44 derivation path → cross-wallet import работает

Option A — 30 минут. Option B — недели (SLIP-44 registration + backward-incompatible breaking change существующих addresses).


CF-4 — Reality keys + UUID в 19 местах ([C-1] SSOT violation)

Класс: SSOT. Severity: средний.

Поверхность: см. 04-Сетевой-слой.md §15.

Closure path: Phase 2 — Rust crate mt-vpn-config-gen читает keys из mt-genesis::ProtocolParams::reality_keys, генерирует все 19 конфигов.

Cost estimate: 3 дня.


CF-6 — https://montana.local/ synthetic baseURL

Класс: production naming [C-12]. Severity: низкий.

Closure: переименовать в https://montana.quest/app/ (синтетический, naружу не идёт). 5 минут.


F-3.1 — Automated purge cron отсутствует

Класс: state lifecycle (Pass 18). Severity: низкий.

Closure: добавить systemd timer montana-vpn-balance-purge.timer daily + автоматический вызов в самом heartbeat (раз в 1000 операций). 1 час.


CF-recovery-tests — Recovery E2E test отсутствует

Класс: Pass 20 user recovery trace. Severity: высокий.

Поверхность: см. 06-Восстановление.md §4. Нет automated test что mnemonic → adr воспроизводимо между устройствами.

Closure path:

  • Add BIP39DerivationTest.kt unit test (JVM) — берёт известный mnemonic, проверяет адрес против hardcoded expected hex
  • Add RecoveryE2ETest.kt instrumented test — то же, но в реальном WebView

Cost estimate: 2 дня.


F-reality-pq — Reality X25519 не пост-квантово

Класс: [I-1] PQ-secure compliance. Severity: низкий (на горизонте 10 лет).

Поверхность: Reality использует X25519 для key exchange — уязвим к квантовому компьютеру (Shor).

Closure path: upstream XTLS реализация PQ-Reality (work in progress, не наша работа). На горизонте 5-10 лет (CRQC threat model).


F-keystore-backup — Genesis keystore без backup procedure

Класс: operational security. Severity: высокий.

Поверхность: /Users/kh./Python/Ничто/Montana/Android/keystore/montana.keystore хранится только на устройстве автора. Компрометация = malicious APK подписи.

Closure path: HSM или Shamir-split keystore на N доверенных лиц с threshold.


Roadmap закрытия

Phase 2 (M-VPN-1, ~1-2 недели) — Rust backend

  • Заменить Flask app.py на Rust mt-vpn-balance (axum + sqlx + SQLite WAL)
  • F-4 mitigation: rsync replication на 3 узла Montana
  • CF-4 closure: mt-vpn-config-gen бинарь читает Reality keys из единого источника
  • F-3.1: cron purge
  • CF-recovery-tests: unit + instrumented tests
  • F-7: backup verify screen
  • F-8: UI warning

Phase 3 (M-VPN-2/3, ~3-4 недели) — TimeChain integration

  • F-2 + F-4 final closure: новый opcode 0x06 VpnHeartbeat в Montana Protocol v35.26
  • mt-account реализация apply_vpn_heartbeat (50+ тестов)
  • montana-node accepts heartbeat в mempool → cemented через consensus
  • AccountRecord.balance обновляется через canonical apply pipeline
  • Android JNI bridge для Falcon-512
  • F-6 closure: encrypted seed через user passcode

Phase 4 (опциональная, поздно) — Hardening

  • F-reality-pq: переход на PQ-Reality когда XTLS upstream готов
  • F-keystore-backup: HSM или Shamir split