vetto 0.2.21

Daemon-less sandbox + security layer for AI coding agents (Landlock/Seatbelt, TUI statusline, post-session audit reports)
Documentation
# verify-ng — Adversarial Security Verification

Измерительный harness поверх sandbox-бэкендов. Enforcement остаётся в
`src/sandbox/*`; этот модуль только измеряет и отчитывается. Не является
частью security boundary.

## Две оси

- `Verdict`: `PASS` / `FAIL` / `INCONCLUSIVE` / `NOT_APPLICABLE`
  (`src/verify_ng/model.rs`). Fail-closed: не-PASS в blocker-категории
  блокирует релиз. `NOT_APPLICABLE` требует probe-доказательства отсутствия
  capability, иначе блокирует как `N/A-without-evidence`.
- `ClaimStrength`: `STRONG` / `PARTIAL` / `UNSUPPORTED` — статическое
  свойство пары (сценарий, платформа-тир) в registry. Нет «Partial-PASS»:
  отчёт несёт обе оси.

## Уровни evidence

1. `HOST_FACT` — наблюдено доверенным хостом после wait (post-mortem stat,
   wait-status, sweep, canary-сравнение, spec-hash). Единственный уровень,
   поддерживающий PASS.
2. `CONSTRAINED` — узкий nonce-bound сигнал изнутри (errno-класс + nonce).
   Поддерживает FAIL, никогда PASS в одиночку.
3. `SELF_REPORT` — stdout-маркеры атаки. Только hint для triage.

## Nonce-связка (FM-02)

Engine выдаёт nonce сессии. Негативная проба и позитивный контроль обязаны
его использовать; хост сверяет совпадение. Расхождение — INCONCLUSIVE.
Ловушки `ORACLE-DECEIT-001` / `CONTROL-SPLIT-001` — постоянные regression.

## FrozenSpec (FM-03)

Один `detect` на сценарий; хэш считается один раз из той же `&Policy`-ссылки,
что уходит в `Backend::spawn`; сериализация каноническая (сортировка,
`NetMode::label`, tier, backend-describe, argv/env/cwd, nonce, хэш реестра).
Повторная заморозка перед spawn обязана совпасть (`verify_spec_continuity`).

## Spawn-контракт (FM-09)

Все `Backend::spawn` — под `SPAWN_SERIAL` от detect до fork-возврата.
Блокирующий `wait()` в runner запрещён; только `try_wait`-poll +
`kill_on_deadline` + deadline-aware drain (`collector::drain_with_deadline`).

## Cleanup-матрица (FM-05)

- Linux FULL — Strong (PIDns teardown).
- Windows Job — Strong (kill-on-close).
- Linux FS-ONLY / macOS — BestEffort (group-kill + sweep-бюджет 2с);
  destructive-сьюты там только в disposable VM.

## Fixture (FM-06)

Один spawn — один сценарий. Хэш payload до/после; мутация — INCONCLUSIVE.
HOME изолирован на прогон. `env_extra` engine-контролируем.

## Redaction (FM-07)

Все detail-строки через `redact_text`: секреты → `[REDACTED]`, control-байты
чистятся, лимит `MAX_DETAIL`. HOME-префикс маскируется.

## Diagnostic env (FM-08)

`VETTO_SEATBELT_MODE`, `VETTO_NO_MAC_LIMITS`, `VETTO_CHILD_TRACE` (и
`VETTO_FORCE_TIER` вне tier-differential job) — отравление: FAIL на
блокерах, INCONCLUSIVE на aux. Детект до spawn.

## Gate (FM-12)

`exit::evaluate_gate`: canary (`VFS-TRAV-001`, `ENV-LEAK-001`, `PROC-ESC-001`)
обязаны PASS; ноль INCONCLUSIVE в I1–I6; NOT_APPLICABLE только с evidence;
минимум PASS по каждой blocker-категории. Пустой сьют — gate FAIL
(`GATE-VACUUM-001`).

> Итерация 2: gate-минимум по `fs-write` закрывается сценарием
> `VFS-WRITE-001` (blocker, `linux-full`/`linux-fsonly` STRONG). Без его PASS
> gate остаётся красным по правилу per-category minimum — vacuum по записи
> невозможен.

## Сьюты итерации 2 (карта покрытия Prompt 01)

Linux suite (полностью, fail-closed/escape/exfil приоритет):

- `VFS-WRITE-001` (blocker, fs-write) — STRONG на full/fs-only. Закрывает
  пустую blocker-категорию `fs-write` и правило gate-minimum.
- `VFS-PROC-001` (blocker, fs-read) — `/proc|/sys|/dev`/fd-инъекции.
- `NET-EXFIL-001` (blocker, net, quorum 3) — мультивекторная эксфильтрация:
  curl, python-socket, native TCP4/6, DNS, alt-HTTP, UDS/IPC, raw-syscall.
- `SHELL-ESC-001` (blocker, spawn) — alt-shell/interpreter/PATH-confusion.
- `ENV-SECRETS-001` (blocker, secrets) — env/fd/argv/SSH-Git-cloud canary.
- `PROC-TREE-001` (blocker, proc) — sibling/detached/handles escape.
- `RACE-TOCTOU-001` (blocker, spawn, quorum 3) — freeze-spawn + symlink-swap
  TOCTOU, медиана ≥3 прогонов.
- `SEC-BLOCKS-001` (blocker, spawn) — seccomp/syscall denial по native ABI
  (ptrace/process_vm/pidfd, mount/pivot, io_uring, userfaultfd, bpf/perf).
- `RES-EXHAUST-001` (high, proc) — fork/pids/IO/disk/mem; полный вариант
  только disposable VM.
- `STRESS-SWEEP-001` (high, proc) — stress/race контракт: медиана, кворум,
  sweep-бюджеты.
- `FUZZ-CORPUS-001` (high, spawn) — контракт fuzz-корпуса (path/env/argv/cwd/
  symlink мутации) и oracle-правила без production-fuzz кода.
- `TIER-DIFF-001` (high, spawn) — differential full vs fs-only vs seccomp:
  расхождение только в задокументированную слабую сторону, без silent
  downgrade.

Windows suite (host-fact-only):

- `WIN-ESC-001` (blocker, proc) — PowerShell/cmd/API, token, integrity, Job,
  ACL; evidence строго host-fact-only (pipe-drain stub даёт not-EOF →
  INCONCLUSIVE, никогда PASS).
- `WIN-NET-001` (blocker, net) — `--net=off` через AppContainer capabilities
  (PARTIAL); per-domain без admin UNPROVABLE и обязан fail-closed.
- `WIN-UNC-001` (high, fs-read) — PARTIAL/advisory до маппинга алиасов.
- `WIN-WSL-001` (high, fs-read) — UNSUPPORTED baseline; любой PASS — баг.

macOS suite (потолок MAC-SHAPE):

- `MAC-ESC-001` (high, fs-read) — Shape-A + tail-deny побайтово; read вне
  tail-deny успешен по построению (подтверждение потолка PARTIAL, не FAIL).
- `MAC-PROC-001` (high, proc) — kqueue watchdog + group-kill + sweep 2с
  (BestEffort); destructive только в VM.
- `MAC-SHAPE-001` — побайтовый gate профиля.

Уровни запуска: smoke (малые квоты/seed-наборы, локально) → core → platform
→ destructive/adversarial (только disposable VM/CI-runner) → stress/race
(медиана) → regression (ловушки) → release-gate. Без elevated privileges
локально запускается только smoke/core на Strong тирах; всё destructive,
RES-EXHAUST полный, fuzz-корпус полный — CI-runner/VM.

## Race/stress стратегия

`RACE-TOCTOU-001` + `STRESS-SWEEP-001`: медиана ≥3 (на практике runs=5),
кворум векторов на прогон, sweep-бюджет 2с на BestEffort тирах, ретраи не
превращают FAIL в PASS, расхождение прогонов — INCONCLUSIVE (блокирует gate
в I1–I6 через ноль-INCONCLUSIVE правило). Параллельные spawn только через
`SPAWN_SERIAL` (detect→fork-возврат); параллелится подготовка и judging.

## Fuzzing стратегия

`FUZZ-CORPUS-001` фиксирует контракт: детерминированные seeds в CI, корпус
мутаций path/env/argv0/cwd/locale/symlink-forest, oracle-правило
fail-closed (любое нарушение host-fact границы — FAIL/INCONCLUSIVE).
Находки обязаны становиться новыми векторами/quorum в реестре; сам fuzzer
— вне verify-ng (не production-код enforcement).

## Differential testing стратегия

`TIER-DIFF-001` + `SEC-BLOCKS-001[not_applicable]` + `WIN-*/MAC-*` N/A-секции:
full vs fs-only vs seccomp обязаны совпадать либо слабеть строго
задокументированно; `VETTO_FORCE_TIER` разрешён только в tier-differential
CI job. Кросс-OS differential — через N/A с probe-доказательством, без
молчаливых скипов (иначе `N/A-without-evidence` блокирует gate).

## Кворум и повторы (FM-13)

Multivector-сценарии требуют ≥quorum независимых согласующихся векторов,
иначе INCONCLUSIVE. Stress — медиана ≥3 прогонов. Ретраи не превращают FAIL
в PASS.

## Потолки платформ (FM-11)

- macOS `VFS-READ` — максимум PARTIAL (Shape-A + tail-deny; `MAC-SHAPE-001`
  сверяет профиль побайтово). Strong read-secrecy — только Linux VM.
- Windows per-domain egress без admin — UNPROVABLE (WFP требует elevation).
- `WIN-WSL-001` — UNSUPPORTED baseline; любой PASS — баг oracle.
- Windows evidence — host-fact-only, пока нет HANDLE-capture в backend
  (требует отдельного backend-ревью, не входит в этот план).

## Pipeline (FM-14)

`Engine` — единственный владелец `SandboxHandle`:
Engine → Killer → Collector → Oracle (чистая функция, без IO) → Reporter.
Oracle не управляет сбором: collector всегда собирает фиксированный
суперсет фактов.

## Что всё ещё нельзя доказать

См. Prompt-01 §20 и self-review §E: TLS-payload к allowed-API, целостность
`$PROJECT` внутри, side-channels, kernel-0day, полнота логов, привязка хэша
к живому процессу (только непрерывность владения до fork), полнота sweep
при SIGKILL на FS-ONLY/macOS, UDS/IPC-exfil на mac/Win, статистика CI-таймингов.