# 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