66 lines
9.1 KiB
Markdown
66 lines
9.1 KiB
Markdown
# Suivi des corrections de sécurité — 9 septembre 2026
|
||
|
||
Branche : `check_secu`, issue de `preparation_prod`, base `8446f879b676b303fdb2891388f88ff7e43f5fea`.
|
||
|
||
Des correctifs ont été appliqués aux 14 constats du rapport initial. Ils sont locaux, non commités et non déployés. Cela ne constitue pas une attestation de sécurité complète du site.
|
||
|
||
## Audit approfondi : échec, couverture incomplète
|
||
|
||
Le rapport initial reste un audit statique partiel : 95 fichiers lus intégralement, plus des lectures ciblées. La tentative d’audit approfondi n’a renvoyé aucun manifeste de découverte réussi. Aucun nouveau scan réussi ni absence de vulnérabilités ne sont revendiqués.
|
||
|
||
Erreur retournée par le coordinateur :
|
||
|
||
> Deep Scan stopped after 3 consecutive unsuccessful discovery workers (limit: 3); last failure (transient_error): You've hit your usage limit. Upgrade to Pro (https://chatgpt.com/explore/pro), visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at 5:47 PM.
|
||
> This is a terminal failure of this logical Deep Scan; no successful discovery manifest was returned.
|
||
|
||
Le coordinateur impose l’arrêt de cette tentative. Les corrections ci-dessous reposent sur les constats déjà conservés et leur vérification locale, pas sur une prétendue couverture exhaustive. Aucun nouveau candidat issu de cette tentative n’a été retourné. Son identifiant n’a pas été fourni dans la réponse d’échec ; son contexte durable n’a donc pas pu être relu par identifiant.
|
||
|
||
## Corrections et preuves
|
||
|
||
| Constat | Modification | Vérification / limite |
|
||
| --- | --- | --- |
|
||
| Modification inter-organisations | Toute cible étrangère est refusée à un acteur non ADMIN. | Tests MANAGER majuscule/minuscule, USER, VIEWER ; mises à jour propres et ADMIN conservées ; 404 conservé. |
|
||
| XSS après connexion | Redirections limitées aux chemins internes ; protocoles, doubles slashs, antislashs et contrôles refusés. | Tests du helper et du contexte React, avec destinations malveillantes et navigation localisée légitime. |
|
||
| Authentification WebSocket | Réutilisation de JwtStrategy ; type access, expiration et compte courant contrôlés à la connexion, aux messages et avant émission. | Tests refresh, type inconnu, expiration, désactivation après connexion et connexion valide. L’émission sortante a aussi été revue statiquement. |
|
||
| Notifications d’autres utilisateurs | UUID validés dans le service ; prédicat ORM `{ id, user_id }` ; propagation de l’utilisateur REST et WS. | Objets, tableaux, chaînes invalides rejetés ; mise à jour du propriétaire conservée, autre destinataire exclu. Test du prédicat avec repository simulé, sans PostgreSQL réel. |
|
||
| Jeton transporteur divulgué | Retrait du jeton du DTO client, du mapper et du type frontend. | Test du mapper ; données métier conservées ; appels d’email transporteur conservés. Les anciens jetons déjà exposés ne sont pas invalidés par cette suppression. |
|
||
| Mutations VIEWER | Rôles ADMIN/MANAGER/USER requis pour création, paiements, modifications et documents CSV. | Test HTTP : VIEWER refusé en création et lecture personnelle conservée. Les autres routes ont été vérifiées par inspection des gardes. |
|
||
| Liste organisation sans rôle | Rôles ADMIN/MANAGER requis pour les listes et statistiques globales de l’organisation. | Test HTTP refusant la liste globale à USER. |
|
||
| Secrets dans les logs | Suppression du mot de passe temporaire et du lien d’invitation ; journalisation par ID ; erreurs d’email sans contenu secret ; suppression des traces brutes de réservation. | Tests de création de compte et d’invitation, y compris exception contenant un token ; lien transmis au service d’email conservé, sans envoi réel. |
|
||
| Anciennes sessions après changement de mot de passe | Tokens liés par HMAC au hash courant du mot de passe ; vérification pour access et refresh. | Anciennes sessions rejetées après changement ; nouvelle connexion/refresh et modification de profil légitimes préservés. Aucun hash de mot de passe n’est mis dans le JWT. |
|
||
| Téléversements mémoire | Limites Multer : 10 Mio/fichier, nombre de fichiers, champs, parties et taille des champs. | Test HTTP d’un fichier dépassant la limite : 413 avant service ; petit fichier accepté. Pas de test de charge ni mesure de mémoire en production. |
|
||
| Manager modifiant un ADMIN | Refus de toute modification d’un compte ADMIN par un acteur non ADMIN. | Tests refus sans mutation/persistance et modification d’un utilisateur ordinaire autorisée. |
|
||
| Clé SMTP littérale | Remplacement par une variable obligatoire de déploiement dans `docker-compose.full.yml`. | Vérification statique ; valeur non reproduite dans les rapports. Pas de validation fournisseur ni révocation effectuée. |
|
||
| Formules CSV | Encodeur commun aux deux exports CSV, appliqué aux valeurs formatées et aux en-têtes. | Tests des préfixes de formule, espaces/contrôles, échappement et zéro ; exports XLSX existants préservés par leurs tests. |
|
||
| Résiliation conservant un plan payant | Transition de résiliation vers Bronze indépendante des plafonds et du statut précédent ; erreur HTTP en cas d’échec du webhook. | Tests état inactif, événement répété, nombre excessif de licences et échec de traitement non acquitté comme succès. Signature Stripe reste vérifiée par l’adaptateur existant ; Stripe réel non appelé. |
|
||
|
||
## Stratégie et compatibilité
|
||
|
||
Les corrections sont placées aux frontières partagées : contexte d’authentification frontend, validation de session backend, service/repository de notifications, gardes HTTP, sérialisation des réponses et transition de domaine de résiliation. Une investigation indépendante avant modification et une revue indépendante du diff ont été effectuées. La revue n’a retenu aucun contournement ou régression confirmé ; elle reste statique.
|
||
|
||
La liaison des sessions utilise le hash déjà stocké et un HMAC avec le secret JWT, plutôt qu’une nouvelle colonne de base de données. Un changement de mot de passe change cette liaison. Les tokens antérieurs au correctif n’ont pas cette liaison et seront refusés : une reconnexion générale est attendue au déploiement. Une modification de profil ne révoque pas les sessions.
|
||
|
||
Les chaînes CSV ressemblant à des nombres négatifs sont volontairement exportées comme texte afin de neutraliser les formules. Le chemin XLSX conserve ses valeurs typées.
|
||
|
||
## Vérifications exécutées
|
||
|
||
- Backend : `npm test -- --runInBand --testPathIgnorePatterns=csv-bookings.security.spec.ts` : 427 tests réussis, 5 déjà ignorés. Après ajout des tests de logs : `users.security.spec.ts` (3 réussis, dont 1 nouveau) et `invitation.security.spec.ts` (1 réussi). Total distinct vérifié hors HTTP : 429 tests.
|
||
- HTTP backend : `npm test -- --runInBand csv-bookings.security.spec.ts` : 5 tests réussis avec serveur éphémère sur `127.0.0.1`. Première tentative bloquée par le sandbox (`listen EPERM`), puis exécution autorisée réussie.
|
||
- Frontend : suites `safe-login-redirect.test.ts`, `auth-context.test.tsx`, `csv-cell.test.ts` et `export.test.ts` : 62 tests réussis. Exécutées via Jest/ts-jest et une configuration temporaire explicite pour éviter le chargement automatique des fichiers `.env` par `next/jest`.
|
||
- `npm run build` backend : réussi.
|
||
- `npm run type-check` frontend : réussi.
|
||
- ESLint sans correction automatique sur les fichiers backend/frontend modifiés : réussi.
|
||
- Prettier sur les fichiers TypeScript modifiés et `git diff --check` : réussis.
|
||
|
||
Des échecs intermédiaires ont été corrigés : insertion d’un contrôle au mauvais emplacement détectée par TypeScript, et en-têtes XLSX altérés détectés par les tests d’export. Les vérifications concernées ont ensuite réussi. Aucun assouplissement de sécurité n’a été introduit pour faire passer les tests.
|
||
|
||
## Actions de production et travail restant
|
||
|
||
1. Renouveler la clé SMTP chez le fournisseur, configurer la nouvelle valeur hors du dépôt, puis déployer. L’historique Git contient encore l’ancienne valeur ; sa suppression du fichier courant n’est pas une révocation.
|
||
2. Invalider/remplacer les jetons transporteur et invitations susceptibles d’avoir été exposés avant le correctif ; prévoir les nouveaux liens légitimes. Aucun email réel n’a été envoyé ni jeton de production modifié.
|
||
3. Prévoir la reconnexion des utilisateurs au déploiement et vérifier les parcours navigateur, transporteur et paiement en préproduction.
|
||
4. Vérifier en environnement réel les limites du reverse proxy, le stockage S3, TLS, les permissions et les journaux historiques. Aucune modification de configuration en production n’a été effectuée.
|
||
5. Terminer l’audit des fichiers non couverts et l’inventaire des vulnérabilités des dépendances lorsque le scanner redevient disponible. Aucun audit exhaustif de dépendances ni pentest déployé n’est revendiqué ici.
|
||
|
||
Les fichiers `.env` et `.env.*` n’ont pas été lus. Aucune migration, fusion, publication, modification de compte fournisseur ou réécriture d’historique n’a été effectuée.
|