xpeditis2.0/audit_security/frais-erreur-abonnement/frais-erreur-abonnement.md

3.8 KiB
Raw Blame History

OBS-01 — Une erreur de lecture d'abonnement devient un forfait gratuit

Mise à jour du 17 septembre 2026 : voir le compte rendu de correction. Le texte ci-dessous conserve le constat avant cette passe. La panne de tarif est désormais refusée avant les effets de bord ; contrôles légitimes préservés.

Statut : comportement confirmé dans le code, exploitation contrôlable non validée. Pas de gravité de vulnérabilité attribuée à ce stade. Cette observation n'entre pas dans le nombre des 18 constats historiques confirmés.

Ce que fait le code actuel

Dans apps/backend/src/application/services/csv-booking.service.ts, resolveBookingFeeEur, lignes 253–262 de l'état local du 14 septembre, attrape toute erreur de getOrCreateSubscription, écrit un message et retourne zéro :

    } catch (error: any) {
      this.logger.error(`Failed to resolve booking fee: ${error?.message}`);
      return 0;
    }

Le même fichier, createBooking, lignes 168–172, utilise ce montant pour choisir la nécessité du paiement :

    const bookingFeeEur = await this.resolveBookingFeeEur(organizationId);
    const requiresPayment = bookingFeeEur > 0;
    const initialStatus = requiresPayment
      ? CsvBookingStatus.PENDING_PAYMENT
      : CsvBookingStatus.PENDING;

Le montant zéro est aussi employé par l'offre sur mesure : l'erreur technique devient donc indiscernable d'une décision commerciale légitime. La réservation est ensuite créée dans le repository. acceptBooking appelle également le calcul des frais et applique le résultat à la réservation.

Scénario à vérifier et limites

Un utilisateur habilité à créer une réservation pourrait bénéficier de l'absence de paiement automatique si la récupération de son abonnement échoue à cet instant et que les étapes suivantes fonctionnent. Mais le contrôleur lit déjà l'abonnement pour son quota et la création persiste ensuite dans la base. Une panne totale et permanente de PostgreSQL pourrait empêcher toute la réservation ; elle ne démontre pas ce contournement.

Il faut donc établir une erreur sélective, transitoire ou propre à la résolution de l'abonnement, suivie d'une sauvegarde réussie. La possibilité pour un attaquant ordinaire de provoquer ou d'exploiter cette situation n'est pas démontrée. Une simple lecture du catch ne permet pas d'affirmer qu'un utilisateur peut réserver gratuitement à volonté.

Validation nécessaire

Sur des doubles locaux, faire réussir la lecture du quota, échouer uniquement le calcul des frais, puis autoriser la sauvegarde. Observer le statut et le montant réellement transmis au repository. Comparer avec une offre réellement gratuite/sur mesure, puis avec une base totalement indisponible. Le contrôle déterminant doit montrer l'absence de paiement uniquement dans le cas d'erreur ciblé et non par une offre légitimement sans forfait.

Aucun de ces nouveaux tests n'a été exécuté pendant cette passe documentaire. Il n'est pas nécessaire de provoquer une panne de production.

Principe recommandé, sans modification appliquée

Une impossibilité de déterminer le prix doit rester une erreur ou un état explicitement non payable tant que le tarif n'est pas connu ; elle ne devrait pas devenir un tarif nul. Le choix exact doit préserver les offres réellement sur mesure et empêcher une notification transporteur prématurée.

Sources : service, contrôleur CSV. L'observation est distincte de SEC-18, qui corrige un statut ignoré et non la gestion d'une panne.