diff --git a/tasks/todo.md b/tasks/todo.md index 49d6d85..887b4d5 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -1,73 +1,115 @@ -# Sprint 9 — UI: engagement 2-col + global contrast pass +# Sprint 10 — C2 TLS verify: redteam-friendly defaults + warning suppression -**Base**: `sprint/8-c2` (sprint 8 not yet merged on origin/main, but its `C2ConfigCard` is the right pane). -**Scope**: frontend-only. No backend, no schema. No new features. +**Base**: `origin/main` (PR #11 merged — sprint 8 + 9 are in). +**Branch**: `sprint/10-c2-tls-default`. +**Scope**: tiny correctness sprint. No new feature. Flip a security-relevant default to match the actual operator usage of this tool. + +--- + +## Symptom (user report) + +> "Impossible de se connecter à mon C2 à cause de la vérification du certificat SSL (self signed)" + +Operator opens C2 config card, fills URL + token, hits **Test connection** without noticing the checkbox → SSL VERIFY FAILED against self-signed Mythic. + +## Root cause (workflow diagnosis confirmed) + +The `verify_tls` chain is **fully intact** end-to-end : +React `verifyTls` state → `C2ConfigInput.verify_tls` → PUT body → `C2Config.verify_tls` column → `cfg.verify_tls` in API loader → `get_adapter(verify_tls=)` → `MythicAdapter._verify` → `requests.post(verify=self._verify)`. + +The bug is the **default** at every layer is `True` : +- `backend/app/models/c2_config.py:22` — `default=True` +- `backend/migrations/versions/0006_c2_layer.py:29` — `server_default=sa.true()` +- `backend/app/api/c2.py:87` — `data.get("verify_tls", True)` +- `backend/app/services/c2/mythic.py:116` — `verify_tls: bool = True` +- `backend/app/services/c2/factory.py:9` — `verify_tls=True` +- `frontend/src/components/C2ConfigCard.tsx:27` — `useState(true)` +- `frontend/src/components/C2ConfigCard.tsx:74` — reset on delete `setVerifyTls(true)` + +Mimic is a BAS / red-team lab tool ; the dominant case is a **self-signed Mythic instance**, not a publicly-trusted cert chain. Defaulting `verify=True` is hostile to the actual workflow. + +Secondary defect : `urllib3.exceptions.InsecureRequestWarning` is never suppressed (zero hits for `disable_warnings` / `urllib3` in `backend/`). When operators correctly uncheck verify, stderr gets spammed once per HTTP call. --- ## Decisions (locked) -1. **Engagement page** : passer en **2 colonnes** sur desktop (`lg:grid-cols-2`), `[engagement form | C2ConfigCard]`. Mobile/tablet : stack vertical (comportement actuel). -2. **Contraste global** : le problème est que `canvas` (page bg) et `paper` (card bg) sont **tous deux `#ffffff`** en light mode. Les cartes ne ressortent que par leur hairline 1px → fatigue oculaire confirmée par l'utilisateur. -3. **Fix retenu** : **tinter le canvas light** d'un neutre froid très pâle. `paper` reste blanc pur. Les cartes "lèvent" naturellement sans casser le brutalisme. - - Proposition : `canvas` light `#f3f5f8` (gris-bleu très pâle, cohérent avec l'electric blue), `paper` light `#ffffff`. - - Dark mode **inchangé** (`canvas #111827` / `paper #1f2937` déjà différenciés). -4. **Pas de shadow**, pas de radius. La brutalité reste intacte — seul le contraste de surface change. -5. **Hairline** : à vérifier sur le nouveau canvas. Si nécessaire, passer `hairline` light de la valeur actuelle à un poil plus sombre pour préserver la lisibilité du bord sur tinted canvas. Mais éviter si la lecture est déjà bonne. +1. **Flip default to `False` at every layer** — model, API fallback, adapter, factory, React state, delete reset. +2. **New migration 0008** : flip `server_default` to `sa.false()`. Existing rows are NOT mutated (their stored boolean is preserved). +3. **Suppress `urllib3.InsecureRequestWarning` ONLY when `verify_tls=False`** — gated inside `MythicAdapter.__init__`. Keeps the warning live for any future code that legitimately verifies. +4. **Add helper text under checkbox** : "Leave unchecked for lab Mythic with self-signed certificates." Operators see why the box matters. +5. **No API contract change** — `C2ConfigInput.verify_tls: boolean` stays required. The fallback in `data.get("verify_tls", False)` only matters for hand-crafted requests. + +## Out of scope + +- Don't touch existing C2 endpoints behavior (route paths, payload shapes). +- Don't change the `verify_tls` field type or remove the column. +- Don't change the FakeAdapter (it makes no HTTP calls). --- -## Task A — EngagementFormPage 2-col - -**File** : `frontend/src/pages/EngagementFormPage.tsx` - -- Remplacer le wrapper `