> ## Documentation Index
> Fetch the complete documentation index at: https://docs.snakysec.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SECURITY

# SECURITY — Threat model & security baseline

Posture sécurité de la plateforme MSSP SnakySec. Cette base sert de réf pour les audits internes et pour alimenter la PSSI générée aux clients.

***

## Cadre transverse : DICT

Modèle ANSSI — chaque contrôle, chaque artefact, chaque risque est classifié sur 4 axes :

| Axe                 | Définition                                              | Exemples dans la plateforme                                                                                       |
| ------------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **D**isponibilité   | Maintien en condition opérationnelle du service         | Vault Shamir seal 5/3 (tolérance 2 shares perdus simultanément), BullMQ retry, DB backups, monitoring Sentry      |
| **I**ntégrité       | Non-altération des données et des contrôles             | HMAC webhook GitLab, schema v3 Zod validation à l'import, audit log immuable (`PlatformAuditLog`), commits signés |
| **C**onfidentialité | Protection des données contre divulgation non autorisée | AES-256-GCM secrets clients, cert X.509 pour Graph, TLS partout, scrubbing PII Sentry, RBAC 3 rôles               |
| **T**raçabilité     | Journalisation des événements de sécurité               | `PlatformAuditLog` applicatif, `ControlReviewHistory`, Sentry breadcrumbs, logs Traefik, GitLab pipeline logs     |

**Principe** : chaque décision sécurité doit pouvoir être rattachée à ≥1 axe DICT. Les 220 contrôles audités sont tagués sur ces 4 dimensions (cf. `scripts/tag-dict.ts`, champ `dict` dans chaque JSON de framework). Les résultats d'audit agrègent un score par axe (`AuditRun.dictSummary`) restitué :

* en radar sur la page d'audit (dashboard MSSP + portail client)
* en filtre multi-axes sur la table de contrôles
* en section dédiée du rapport PDF d'audit
* comme classification de référence dans le PSSI généré

Voir [docs/LOGGING.md](./LOGGING.md) pour l'axe T (traçabilité) et la chaîne de preuve numérique.

***

## Architecture de secrets

### Principe zéro long-lived secret

* **CI/CD** → OIDC Workload Identity Federation (GitLab → Entra). Le token est un JWT OIDC émis par GitLab, vérifié par Entra qui émet un access token Graph. Aucun secret ne transite.
* **Production runtime** → cert X.509 pour Graph (public dans Entra app, privé dans Vault uniquement).
* **Dev** → mêmes chemins qu'en prod (Vault dev mode), jamais de client secret.

### Vault

* **Prod** : Shamir seal, 5 shares, threshold 3. Répartition : 3 shares détenues par le DR Owner (YubiKey + KeePass cloud chiffré + papier coffre domicile A2P ignifuge) et 2 shares en enveloppe scellée Tyvek chez un notaire mandaté avec clause d'activation conditionnelle (décès, incapacité, décision de justice, demande conjointe). Cf. [dr/01-keyholders.md](./dr/01-keyholders.md) pour la procédure complète et [dr/00-policy.md](./dr/00-policy.md) pour la politique DR.
* **Dev** : dev mode avec root token statique — seulement en local, jamais exposé.
* **AppRole** :
  * `mssp-app` : `read` sur `mssp/platform` + `mssp/clients/*`
  * `mssp-worker` : `read` sur `mssp/clients/*` uniquement
* Les secret-IDs sont injectés au container via un volume partagé (`mssp-approle`), jamais dans les env vars compose.

### Paths & contenus

| Path                       | Contenu                                                                                                                                                                                                                                                                                                               | Qui lit                   |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| `mssp/data/platform`       | `auth_secret`, `encryption_key`, `entra_cert_pem`, `entra_cert_private_key`, `gitlab_token`, `postgres_password`, `redis_password`, `sentry_dsn`, `sentry_auth_token`, `notifications_client_id`, `notifications_tenant_id`, `notifications_cert_pem`, `notifications_cert_private_key`, `notifications_from_address` | app, worker               |
| `mssp/data/clients/<slug>` | `entra_client_id`, `entra_tenant_id`, `entra_cert_pem`, `entra_cert_private_key`                                                                                                                                                                                                                                      | app (SSO), worker (audit) |
| `mssp/data/dr/*`           | `pgbackrest_cipher_pass`, `restic_password`, `ovh_s3_*`, `scaleway_s3_*`, `ovh_api_*`                                                                                                                                                                                                                                 | dr-runner, postgres       |

### Chiffrement applicatif

* **Secrets client en DB** (`ClientSecret`) → AES-256-GCM, clé `encryption_key` en Vault. Jamais en clair en DB.
* **TLS** → mkcert en dev (`*.localhost`), Let's Encrypt en prod.
* **Cookies SSO** → `httpOnly`, `secure`, `sameSite=lax`, expire avec la session NextAuth.

***

## RBAC

3 rôles applicatifs :

| Rôle          | Scope                                                                                                 |
| ------------- | ----------------------------------------------------------------------------------------------------- |
| `MSSP_ADMIN`  | Tous les clients, toutes les actions (trigger audit, reviewer workflow, GRC docs, impersonate portal) |
| `ANALYST`     | Clients assignés (`ClientUserAccess`), read + reviewer workflow, pas d'admin global                   |
| `CLIENT_USER` | Son propre tenant uniquement (via portal), read-only                                                  |

* Enforcement : `platform/src/proxy.ts` (route-level) + `auth-helpers.ts` (`requireAuth`, `requireRole`, `requireClientAccess`).
* Audit log sur toute action sensible (trigger audit, mark compliant/non-compliant, modification client, export).

***

## Threat model (résumé)

### Surface d'attaque externe

| Vecteur                        | Mitigation                                                                               |
| ------------------------------ | ---------------------------------------------------------------------------------------- |
| Webhook GitLab falsifié        | HMAC signature vérifiée sur `X-Gitlab-Token` avant enqueue BullMQ                        |
| Injection SSO (hostname spoof) | `resolveClientFromCookie()` matche sur `Client.domain` en DB — pas de trust du Host brut |
| Replay token NextAuth          | `AUTH_SECRET` rotated côté Vault invalide toutes les sessions instantanément             |
| CSRF                           | NextAuth CSRF token par défaut + `sameSite=lax` cookie                                   |
| XSS                            | React auto-escape par défaut + CSP headers (Traefik) + pas de HTML injection brute       |
| SQL injection                  | Prisma ORM (paramétrage automatique) — pas de raw SQL utilisateur                        |

### Surface interne

| Risque                      | Mitigation                                                                                                                      |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Compromission container app | Pas de secret Vault persisté hors runtime, cert X.509 jamais écrit sur disque                                                   |
| Élévation inter-tenant      | RBAC `requireClientAccess` systématique, queries Prisma filtrées par `clientId`, RLS PostgreSQL planifié (P2)                   |
| Fuite via Sentry            | Denylist : `AUTH_SECRET`, `ENCRYPTION_KEY`, `*_PASSWORD`, `VAULT_*`, `GITLAB_TOKEN`. Scrubbing email/IP, body truncated > 10 KB |
| Cert X.509 compromis        | Rotation annuelle + révocation immédiate possible (retrait côté Entra app)                                                      |

### Non-mitigations (documentées)

* **Supply-chain npm** : pas de lockfile verification automatisée en CI. Mitigation P3.
* **RLS PostgreSQL** : pas encore actif — défense en profondeur dépend du RBAC applicatif. P2 bloquant avant 1er client payant multi-tenant.
* **Rotation GitLab token** : manuelle, pas de TTL monitoring. Dette technique P3.

***

## Gouvernance

* **Revue sécu** : self-review à chaque commit touchant auth/secrets/RBAC.
* **Threat model update** : à chaque changement d'architecture (nouveau composant, nouveau flux externe).
* **ADR** : décisions immuables dans `docs/adr/` (BullMQ, Vault AppRole, cert X.509, cursor pagination).
* **Incident response** : [runbooks/incident-response.md](runbooks/incident-response.md).
* **Rotation** : [runbooks/key-rotation.md](runbooks/key-rotation.md).

***

## Références normatives

* **ANSSI** — Guide PSSI, SecNumCloud, EBIOS Risk Manager
* **ISO 27001:2022** — A.5 (Organizational) · A.8 (Technological) · A.12 (Operations)
* **NIST CSF 2.0** — Govern / Identify / Protect / Detect / Respond / Recover
* **NIS 2** (Directive UE 2022/2555) — art. 21 (mesures de gestion des risques) · art. 23 (notification d'incident)
* **RGPD** — art. 32 (sécurité du traitement) · art. 33-34 (notification violation)
