# Sécuriser un webhook Stripe qui expose un numéro de commande

> Sept requêtes par seconde en pic de vente, et chacune finissait dans un outil de suivi d'erreurs tiers avec le numéro de commande et le montant en clair.

- Auteur : WordPress Développement
- Publié le : 2023-02-22
- Mis à jour le : 2023-02-22
- Catégorie : Sécurité
- URL : https://www.wpmoderne.fr/securite/securiser-webhook-stripe-numero-commande-expose/

## L’essentiel

- Un webhook Stripe non filtré atterrit tel quel dans les logs tiers
- Scruber avant l'envoi, jamais après
- Un contexte d'erreur générique suffit la plupart du temps

Sept requêtes par seconde. C'est le débit de webhooks Stripe qu'encaissait une boutique à fort volume lors d'un pic de vente, chacune contenant un identifiant de commande, un montant et parfois une adresse de livraison partielle. Le problème n'était pas Stripe, dont le webhook fonctionnait exactement comme prévu, mais ce que la boutique en faisait ensuite : chaque événement, avant même d'être traité par la logique métier, transitait par le SDK d'un outil de suivi d'erreurs tiers configuré pour capturer le contexte de chaque requête entrante.

Résultat : des mois d'historique de commandes, avec montants et identifiants, consultables par quiconque avait accès au tableau de bord de l'outil de monitoring, y compris des prestataires externes n'ayant aucune raison de voir ces données. Voici la checklist à suivre pour éviter ce piège sur toute intégration de paiement qui journalise ses requêtes entrantes.

## Identifier ce qui part vraiment vers l'outil tiers

La première étape consiste à examiner précisément ce que le SDK de suivi d'erreurs capture par défaut. La plupart des intégrations PHP pour ce type d'outil attachent automatiquement le corps de la requête HTTP en cours au contexte de chaque événement remonté, qu'il s'agisse d'une erreur réelle ou d'une simple trace de performance. Sur l'endpoint qui recevait le webhook Stripe, cela signifiait que le payload JSON complet — avec `id`, `amount`, `customer` et parfois `shipping` — se retrouvait attaché à chaque transaction remontée, même celles qui n'avaient rien à voir avec une erreur de paiement.

- Vérifier la configuration d'intégration HTTP du SDK de monitoring (souvent activée par défaut).
- Repérer les points d'entrée qui reçoivent des webhooks de paiement dans le code du site.
- Confirmer si le corps brut de la requête est effectivement transmis ou seulement des métadonnées.

## Scruber avant l'envoi, pas après coup

> L'essentiel à retenir : Un webhook Stripe non filtré atterrit tel quel dans les logs tiers ; Scruber avant l'envoi, jamais après ; Un contexte d'erreur générique suffit la plupart du temps

La tentation est de configurer des règles de masquage côté outil tiers, en marquant certains champs comme sensibles dans son interface. C'est une mauvaise idée : cela suppose que la donnée sensible a déjà quitté le serveur pour atteindre le tiers, où elle reste stockée le temps que la règle de masquage s'applique, et où un export ou une fuite côté fournisseur exposerait la donnée brute historique. Le scrubbing doit avoir lieu avant l'envoi, côté serveur WordPress, jamais après.

```
add_filter( 'monitoring_before_send', function( $event ) {
    if ( isset( $event['request']['data'] ) ) {
        $data = $event['request']['data'];
        unset( $data['id'], $data['amount'], $data['customer'], $data['shipping'] );
        $event['request']['data'] = $data;
    }
    return $event;
} );
```

Ce filtre intercepte l'événement juste avant sa transmission réseau et retire les champs sensibles du tableau de contexte. Le principe s'applique quel que soit l'outil utilisé : la plupart proposent un point d'extension équivalent (« before send », « beforeSend », filtre d'événement) qui s'exécute encore côté serveur.

### Remplacer par un contexte générique suffisant

Un contexte d'erreur utile n'a pas besoin du numéro de commande complet pour être exploitable. Il suffit très souvent de :

- Un identifiant tronqué ou haché, qui permet de recouper avec les logs internes sans exposer la valeur réelle.
- Le statut de l'événement Stripe (`payment_intent.succeeded`, `charge.failed`…).
- Un indicateur de montant par tranche (« < 50 € », « 50-200 € »…) plutôt que la valeur exacte.

## Checklist complète avant mise en production

1. Auditer la configuration par défaut du SDK de monitoring installé sur le site.
2. Désactiver la capture automatique du corps de requête sur les routes de webhook, ou la filtrer explicitement.
3. Ajouter un filtre de scrubbing testé sur un webhook de test Stripe avant tout déploiement.
4. Vérifier que les logs déjà envoyés ne contiennent pas d'historique sensible à purger côté outil tiers.
5. Documenter la liste des champs interdits d'export pour que la règle survive au prochain développeur du projet.

## Un point aveugle fréquent : les logs applicatifs locaux

Le scrubbing vers l'outil tiers ne dispense pas de vérifier les journaux applicatifs locaux. Sur cette boutique, un `error_log()` de débogage laissé actif dans le gestionnaire de webhook écrivait également le payload complet dans les journaux du serveur, hors de portée immédiate mais tout aussi problématique en cas d'accès non autorisé au système de fichiers. La correction a donc porté à la fois sur l'outil tiers et sur ce log local, retiré une fois le débogage terminé.

> Un contexte d'erreur exploitable ne signifie pas un contexte complet : la question à se poser est toujours « de quoi ai-je besoin pour diagnostiquer », jamais « que puis-je capturer ».

## Notre verdict

Ce type de fuite ne vient presque jamais d'une intention malveillante mais d'une configuration par défaut trop généreuse d'un outil tiers légitime. La checklist ci-dessus prend moins d'une heure à appliquer sur un projet existant, et elle mérite d'être intégrée dès l'installation de tout SDK de suivi d'erreurs sur un site qui traite des paiements, avant même le premier webhook réel reçu en production.
