# Audit fixes — implementační plán pro Orchestrátora

**Datum:** 3. 11. 2026  
**Stav:** Připraveno k implementaci  
**Zdroj:** Detailní audit projektu CyberBrain26 (5 subagentů, read-only) + deep-research CVE aktualizace  
**Autoritativní plán:** `.kilo/plans/CyberBrain26cil-031026-v2.md` (beze změny cíle, pouze opravy z auditu)

---

## 1. Cíl

Opravit všechny bezpečnostní problémy z auditu z 3. 11. 2026: 6 nálezů (4× MAJOR, 2× MINOR), CVE v dependencies (litellm, pydantic, pyyaml, bubblewrap) a dokumentaci (AGENTS.md). Orchestrátor nikdy sám nekoná — vždy deleguje dle delegační matice v `.kilo/agent/orchestrator.md`.

---

## 2. Gate 1 baseline (před jakoukoli změnou)

| Brána | Příkaz | Výsledek | Stav |
|-------|--------|----------|------|
| pytest | `PYTHONPATH=src python3 -m pytest -q` | 764 passed, 0 failed, exit 0 | **[ZELENÁ]** |
| ruff src/ | `ruff check src/` | 0 chyb, exit 0 | **[ZELENÁ]** |
| mypy | `mypy src/cyberbrain26` | 87 souborů, bez chyb, exit 0 | **[ZELENÁ]** |

Poznámka: `ruff check` celého repo hlásí 9880 chyb, ale všechny jsou v `archive/` (mimo distribuční balíček, není onderdeel Gate 1/2).

---

## 3. Rozhodnutí (vyřešeno – aktualizováno podle deep-web výzkumu)

| # | Rozhodnutí | Hodnota | Zdroj |
|---|-----------|---------|-------|
| 1 | EgressPermissionGate výchozí rozhodnutí | `base_decision=False` (fail-closed) | Security-auditor nález #1 |
| 2 | LocalClassificationGate prázdné klasifikace | Vrátit `False` (fail-closed) | Security-auditor nález #2 |
| 3 | Non-SAFE módy default_allow | Odstranit, ponechat default deny | Security-auditor nález #3 |
| 4 | CHAIN_KEY | Načítat z env proměnné `CYBERBRAIN_CHAIN_KEY`, fallback selhání | Security-auditor nález #4 |
| 5 | Mrtvý kód v secure_gateway.py | Odebrat větev `if self.egress_gate is None:` | Security-auditor nález #5 |
| 6 | Docstring AuditLog | Opravit tak, aby reflektoval existující hash chain | Security-auditor nález #6 |
| 7 | litellm verze | **Zamknout na `>=1.100.4,<1.101.0`** (bezpečná verze po CVE-2026-114612) | Deep-research CVE výzkum (OSV, GitHub advisories) |
| 8 | pydantic verze | Zamknout na `>=2.14.2` (opravy Fraction DoS, JSON extra-data bypass, alias bypass) | Deep-research CVE výzkum (GHSA-qpmf-fgh3-ff25, GHSA-3r8g-cqwr-jr29, GHSA-gj4f-r7mf-jjxh) |
| 9 | pyyaml verze | `>=6,<7` + **vynutit `yaml.safe_load()`** pro veškerý cizí vstup | Deep-research (PyYAML 6.0.3 bez CVE, ale staré verze kritické) |
| 10 | AGENTS.md | Aktualizovat: 747→764 testů, subagent_depth 1→3, atribuce test_plan_authority.py | Verifier nálezy C1,C2,C8 |
| 11 | bubblewrap | Vyžadovat **verzi ≥0.12.0** (oprava CVE-2026-87766 sandbox escape) | Deep-research CVE výzkum |

---

## 4. Soubory ke změně (s file:line)

### A) `src/cyberbrain26/security_plane/extension_points.py`

**Řádek 68** — `EgressPermissionGate`:
- Staré: `base_decision=True`
- Nové: `base_decision=False`
- Důvod: deny-by-default pro egress povolení

**Řádek 57** — `LocalClassificationGate.evaluate`:
- Staré: vrací `True` pro prázdné `classifications`
- Nové: vrací `False` pro prázdné `classifications`
- Důvod: neklasifikovaná data nesmějí projít klasifikační bránou

### B) `src/cyberbrain26/security_plane/policy/__init__.py`

**Řádky 230-240** — Non-SAFE módy (FULL/RESEARCH/RED_TEAM_LAB):
- Staré: vloženo pravidlo `default_allow` (ALLOW pro `*`)
- Nové: odstranit `default_allow`, ponechat `default_deny` s explicitními allow pravidly
- Důvod: deny-by-default musí platit i mimo SAFE režim

### C) `src/cyberbrain26/security_plane/audit/chain.py`

**Řádek 39** — `CHAIN_KEY`:
- Staré: `CHAIN_KEY: Final[bytes] = b"cyberbrain26-audit-chain-key-v1"`
- Nové: načítat z `os.environ.get("CYBERBRAIN_CHAIN_KEY")`, pokud chybí → vyvolat chybu (fail-closed)
- Důvod: hardcoded klíč umožňuje útočníkovi s přístupem ke kódu a DB přepsat celý audit log

### D) `src/cyberbrain26/execution_plane/secure_gateway.py`

**Řádky 188-197** — Mrtvý kód:
- Odebrat větev `if self.egress_gate is None:` (vždy False, `self.egress_gate` je vždy nastaveno na ř. 125)
- Důvod: matoucí kód bez bezpečnostního dopadu

### E) `src/cyberbrain26/security_plane/audit/__init__.py`

**Řádek 124** — Docstring `AuditLog`:
- Staré: "(SQLite-backed, no hash chain)"
- Nové: popsat existující hash chain (seq, prev_hash, entry_hash, compute_event_hash)
- Důvod: dokumentace neodpovídá implementaci

### F) `pyproject.toml`

**Řádek 33** — litellm:
- Staré: `"litellm>=1.98,<1.99"`
- Nové: `"litellm>=1.98,<1.100"`
- Důvod: CVE GHSA-7hp6-4w63-5g45 (CVSS 9.9, RCE) postihuje verze 1.98–1.99

**Řádek 25** — pydantic:
- Staré: `"pydantic>=2.6"`
- Nové: `"pydantic>=2.14.2"`
- Důvod: dvě Moderate advisories z října 2026 postihují verze 2.6–2.13.x

**Pyyaml** — přidat horní hranici a zajistit `safe_load()`:
- Staré: `"pyyaml>=6"`
- Nové: `"pyyaml>=6,<7"` + v kódu zajistit `yaml.safe_load()` místo `yaml.load()`
- Důvod: chybějící horní hranice a riziko RCE při `yaml.load()` na nedůvěryhodných souborech

### G) `AGENTS.md`

**Řádek 67** — Počet testů:
- Staré: "747 passed"
- Nové: "764 passed"

**Řádek 68** — subagent_depth:
- Staré: "1 (.kilo/kilo.jsonc:6)"
- Nové: "3 (.kilo/kilo.jsonc:6)"

**Řádky 59-61** — Atribuce test_plan_authority.py:
- Opravit: test_kilo_agent_policy.py odkazuje jen na ROADMAP_V6.md §14; pět archivních dokumentů hlídá test_plan_authority.py

---

## 5. Pořadí kroků (pro Orchestrátora)

Orchestrátor deleguje každý krok konkrétnímu subagentovi podle delegační matice. Nikdy sám nekoná.

### Krok 1: Gate 1 ověření (tester)
- Spustit `pytest -q`, `ruff check src/`, `mypy src/cyberbrain26`
- Potvrdit zelenou baseline před jakoukoliv změnou

### Krok 2: Bezpečnostní opravy v security_plane (implementer → security-auditor revize)
Implementer připraví diff pro:
- `extension_points.py:68` — `base_decision=False`
- `extension_points.py:57` — `False` pro prázdné klasifikace
- `policy/__init__.py:230-240` — odstranit `default_allow`
- `chain.py:39` — CHAIN_KEY z env proměnné
- `secure_gateway.py:188-197` — odebrat mrtvý kód
- `audit/__init__.py:124` — opravit docstring

Security-auditor zkontroluje diff před aplikací (vždy pro změny v `security_plane/` a `execution_plane/`).

### Krok 3: Závislosti v pyproject.toml (implementer)
- litellm: `>=1.98,<1.100`
- pydantic: `>=2.14.2`
- pyyaml: `>=6,<7` + zajistit `safe_load()` v kódu

### Krok 4: Dokumentace AGENTS.md (documenter)
- Aktualizovat řádky 67, 68, 59-61 dle bodů C1, C2, C8 z verifier zprávy

### Krok 5: Gate 2 (tester)
- Spustit `pytest -q`, `ruff check src/`, `mypy src/cyberbrain26`
- Porovnat s Gate 1 baseline: musí zůstat zelené

### Krok 6: Receipt kontrola (orchestrátor)
- Jeden příkaz musí potvrdit všechny body receiptu: `git status --porcelain`, `grep -c` na klíčové řádky, `cat -A` na whitespace hlídače
- Rozpor = `REJECT_UNVERIFIED`

---

## 6. Validace (co musí být pravdivé po změně)

| Kontrola | Příkaz | Očekávaný výsledek |
|----------|--------|-------------------|
| pytest | `PYTHONPATH=src python3 -m pytest -q` | 764 passed, 0 failed |
| ruff src/ | `ruff check src/` | 0 chyb, exit 0 |
| mypy | `mypy src/cyberbrain26` | 0 chyb, 87 souborů |
| EgressPermissionGate | `grep -n "base_decision" src/cyberbrain26/security_plane/extension_points.py` | `base_decision=False` |
| LocalClassificationGate | `grep -n "classifications" src/cyberbrain26/security_plane/extension_points.py` | `False` pro prázdné |
| policy default_allow | `grep -n "default_allow" src/cyberbrain26/security_plane/policy/__init__.py` | žádný výskyt |
| CHAIN_KEY | `grep -n "CHAIN_KEY" src/cyberbrain26/security_plane/audit/chain.py` | načítá z `os.environ` |
| Mrtvý kód | `grep -n "egress_gate is None" src/cyberbrain26/execution_plane/secure_gateway.py` | žádný výskyt |
| litellm horní hranice | `grep -n "litellm" pyproject.toml` | `>=1.98,<1.100` |
| pydantic horní hranice | `grep -n "pydantic" pyproject.toml` | `>=2.14.2` |
| pyyaml horní hranice | `grep -n "pyyaml" pyproject.toml` | `>=6,<7` |
| AGENTS.md testy | `grep -n "764 passed" AGENTS.md` | nalezeno |
| AGENTS.md subagent_depth | `grep -n "subagent_depth" AGENTS.md` | `3` |

---

## 7. Rizika a pojistky

| Riziko | Pojistka |
|--------|----------|
| Změna `base_decision` na `False` rozbije existující egress testy | Security-auditor revize před aplikací; Gate 2 po změně |
| CHAIN_KEY z env proměnné rozbije testy bez proměnné | Testy musí nastavit `CYBERBRAIN_CHAIN_KEY` v conftest nebo fixture |
| Odstranění `default_allow` ovlivní nesafe módy | Security-auditor potvrdí, že default deny je správné chování |
| litellm `<1.100` není kompatibilní s nějakým kódem | Testy musí projít po změně verze |
| Zápis do `src/` bez schválení vlastníka | Implementer před aplikací diffu čeká na schválení vlastníka |

---

## 8. Otevřené body (pro vlastníka)

| # | Položka | Stav | Řešení | Vlastník |
|---|---------|------|--------|----------|
| 1 | Souhlas s opravami | Nevyřízeno | Vlastník musí výslovně schválit zápis do `src/`, `tests/`, `pyproject.toml` před implementací | Vlastník |
| 2 | `CYBERBRAIN_CHAIN_KEY` | Nevyřízeno | Vlastník rozhodne, zda se klíč načítá z env proměnné, nebo zda existuje jiný mechanismus správy klíčů | Vlastník |
| 3 | Gate 3 (LLM-as-judge) | Neproběhlo | `gate3-auditor` není dostupný jako Task subagent_type. Vyžaduje jiný model až po Gate 1 i Gate 2. Orches-trátor musí zajistit Gate 3 běh mimo standardní subagenty (přes délégační matice v `.kilo/agent/orchestrator.md`). | Orches-trátor |
| 4 | `safe_load` pro pyyaml | **Není nutno opravit** | V `src/` není žádné `yaml.load()` ani `import yaml`. Soubor `archive/` obsahuje závislosti třetích stran (pandas test suite), ne projektový kód. | — |

---

Plán je připraven k implementaci. Soubor: `.kilo/plans/1793713720824-audit-fixes-implementation.md`